import {Component, OnInit} from '@angular/core';

import {CONSTANTS, NavigationParams, PropertyRow} from 'm2-core';
import {CdDemoComponent} from '../../../abstract/CdDemoComponent';


@Component({
    template: `
        <section class="cd-content-section">
            <h4 i18n>Представление иерархических данных в карточке</h4>

            <p>
                С помощью класса <code cdApiLink="/classes/PropertyRow.html">PropertyRow</code> можно структурировать иерархические данных неограниченной глубины вложенности. Параметры строки описываются типом <code cdApiLink="/miscellaneous/typealiases.html#PropertyRowOptions">PropertyRowOptions</code>.  
            </p>
            
            <div class="cd-demo-widget sdi-card-wrapper">
                <card-rows [rootRows]="cardRows"></card-rows>
            </div>
        </section>
    `
})
export class CdPropertyRowDemoComponent extends CdDemoComponent implements OnInit {

    cardRows?: PropertyRow[];


    ngOnInit(): void {
        this.cardRows = this.formRows();
    }


    /**
     * In real plugin this method should be declared in service
     */
    private formRows(): PropertyRow[] {
        const rows: PropertyRow[] = [
            // simple row
            new PropertyRow(null, 'Наименование', 'Автомобиль')
        ];

        // category row
        const catRow = new PropertyRow(null, 'Габариты', null, { isCategory: true, expandOnInit: true });
        catRow.addChildren(
            new PropertyRow(catRow, 'Длина', '5000')
            ,new PropertyRow(catRow, 'Ширина', '2000')
            ,new PropertyRow(catRow, 'Выстота', '1500')
        );
        rows.push(catRow);

        // link
        rows.push(new PropertyRow(null, 'Ссылка', new NavigationParams(CONSTANTS.GREETING_ROUTER_LINK,
            null, null, null, null, 'на стартовую страницу'))
        );

        // html
        rows.push(new PropertyRow(null, 'Разметка', '<a class="sdi-link" href="https://en.wikipedia.org/wiki/Car" target="_blank">wiki</a>', {
            tip: 'Произвольная разметка в качестве значения атрибута'
        }));

        // highlight
        rows.push(new PropertyRow(null, 'Подсветка текста', 'Лист ДПРХТ  1,9x600x1500 М1 ГОСТ 1173-2006 ', { highlightValue: true }));

        // wrap text
        const longText = 'A car (or automobile) is a wheeled motor vehicle used for transportation. Most definitions of cars say that they run primarily on roads, seat one to eight people, have four wheels, and mainly transport people rather than goods.';
        rows.push(new PropertyRow(null, 'Не переносить по словам (по умолчанию)', longText));
        rows.push(new PropertyRow(null, 'Переносить по словам', longText, { allowWrapValue: true }));

        // hierarchy
        const hierarchyData = genTree(10, 4, 5, (n, lvl, num) => {
            n.name = `${lvl + 1}.${num + 1}. Атрибут`;
        });

        function createRow(node: Node, parent?: PropertyRow): PropertyRow {
            const hasChildren = node.children?.length > 0;
            const row = new PropertyRow(parent, node.name, hasChildren ? null : 'Значение атрибута', {
                params: node,
                isCategory: hasChildren
            });
            node.children?.forEach(child => row.addChildren(createRow(child, row)));
            return row;
        }

        const hierarchyRow = new PropertyRow(null, 'Иерархические данные', null, { isCategory: true, expandOnInit: true });
        hierarchyRow.addChildren(...hierarchyData.map(n => createRow(n, hierarchyRow)));
        rows.push(hierarchyRow);

        return rows;
    }

}


// region @ignore
interface Node {
    name: string;
    children?: Node[];
}

function genTree<N extends Node>(rootsCount: number, maxDepths: number, maxChildren: number,
                 formatNode?: (node: N, level: number, serialNum: number) => void): N[] {
    return Array
        .from({ length: rootsCount })
        .map((_, i) => genNode(0, i, maxDepths, maxChildren, formatNode));
}

function genNode<N extends Node>(level: number, serialNum: number, maxDepths: number, maxChildren: number,
                                 formatNode: (node: N, level: number, serialNum: number) => void): N {
    const node = { name: `${level}.${serialNum}. Node` } as N;
    formatNode?.(node, level, serialNum);
    if (level < maxDepths) {
        node.children = Array
            .from({ length: maxChildren })
            .map((_, i) => genNode(level + 1, i, maxDepths, maxChildren, formatNode));
    }
    return node;
}
// endregion @ignore
