import * as d3 from 'd3';
import ELK from 'elkjs';
import { globalLookup, globalSetting } from '../global';
import { NetlistRender } from '.';

export class ConstantRender {
    /**
     * 
     * @param {d3.Selection} selection 
     * @param {NetlistRender} rootRender
     */
    constructor(selection, rootRender) {
        this.parentSelection = selection;
        this.rootRender = rootRender;

        /**
         * @type {BasicD3DataItem[]}
         */
        this.data = [];

        /**
         * @description id 到管理数据项的映射
         * @type {Map<string, BasicD3ManagmentItem[]>}
         */
        this.id2manager = rootRender.id2manager;
    }

    /**
     * @description 将 elknode 关于 port 的数据添加为 d3 数据项目
     * @param {ElkNode} node 
     */
    addAsD3DataItem(node) {
        let renderString = parseInt(node.name, 2);
        if (isNaN(renderString)) {
            if (node.name.toString().startsWith('x')) {
                renderString = `${node.name.toString().length}{1'bx}`;
            } else {
                renderString = node.name.toString();
            }
        }
        
        this.data.push({
            id: node.id,
            x: node.x,
            y: node.y,
            width: node.width,
            height: node.height,
            text: renderString,
            rx: 3,
            ry: 3
        });
    }

    render() {
        const data = this.data;
        const id2manager = this.id2manager;
        const rootRender = this.rootRender;
        const _this = this;

        let portSelections = this.parentSelection.selectAll('g.port')
            .data(data)
            .enter()
            .append('g')
            .attr('class', 'port')
            .attr("transform", d => `translate(${d.x}, ${d.y})`);
        
        let ports = portSelections.append('rect')
            .attr('width', data => data.width)
            .attr('height', data => data.height)
            .attr('fill', 'var(--constant-fill-color)');
        
        let texts = portSelections.append('text')
            .attr('x', data => data.width / 2)              // 文本的 x 坐标（居中）
            .attr('y', data => data.height / 2)             // 文本的 y 坐标（居中）
            .attr('dominant-baseline', 'middle')            // 文本垂直居中
            .attr('text-anchor', 'middle')                  // 文本水平居中
            .attr('fill', 'var(--foreground)')              // 文本颜色
            .attr('font-size', '12px')
            .attr('class', 'port-caption')
            .text(data => data.text);                       // 设置文本内容


        if (globalSetting.renderAnimation) {
            ports.transition()
                .duration(1000)
                .attr('stroke', 'var(--constant-color)')
                .attr('stroke-width', 2)
                .attr('rx', d => d.rx)
                .attr('ry', d => d.ry);
        } else {
            ports.attr('stroke', 'var(--constant-color)')
                .attr('stroke-width', 2)
                .attr('rx', d => d.rx)
                .attr('ry', d => d.ry);
        }

        portSelections
            .attr('class', 'grab')
            .each(function (data) {                    
                const portSelection = d3.select(this);
                // const manager = _this.createDataManager(portSelection, data);

                // TODO: 实现拖拽
                // registerDragEvent(manager, rootRender);       
            });
            
        this.selections = portSelections;
        return portSelections;
    }

    /**
     * 
     * @param {d3.Selection} selection 
     * @param {BasicD3DataItem} data 
     * @returns {BasicD3ManagmentItem}
     */
    createDataManager(selection, data) {
        const id2manager = this.id2manager;
        // 创建拖拽上下文
        const dragContext = {
            neighbors: [],
            elkGraph: {
                // elk 是无状态的，id 取什么名字都行
                id: 'root',
                children: [],
                edges: [],
                layoutOptions: {}
            }
        }
        const managerItem = {
            data,
            selection,
            type: 'port',
            dragContext
        };

        if (!id2manager.has(data.id)) {
            id2manager.set(data.id, []);
        }

        id2manager.get(data.id).push(managerItem);
        return managerItem;
    }
}




/**
 * @description 注册关于 器件 的拖动事件
 * 
 * 需要提取最小拓扑子图，然后重新调整各个区域的尺寸
 * @param {BasicD3ManagmentItem} manager
 * @param {NetlistRender} rootRender
 */
export function registerDragEvent(manager, rootRender) {
    // 创建拖拽行为
    const drag = d3.drag();

    drag.on("start", event => dragStart(event, manager, rootRender));
    drag.on("drag", event => dragged(event, manager, rootRender));
    drag.on("end", event => dragEnd(event, manager, rootRender));
    
    manager.selection.call(drag);
}

/**
 * @param {d3.D3DragEvent} event 
 * @param {BasicD3ManagmentItem} manager
 * @param {NetlistRender} rootRender 
 */
function dragStart(event, manager, rootRender) {
    const selection = manager.selection;
    selection.attr('class', 'grabbing');
}

/**
 * @param {d3.D3DragEvent} event 
 * @param {BasicD3ManagmentItem} manager
 * @param {NetlistRender} rootRender 
 */
function dragged(event, manager, rootRender) {    
    const selection = manager.selection;
    const data = manager.data;

    data.x = event.x;
    data.y = event.y;
    selection.attr("transform", `translate(${event.x}, ${event.y})`);
}

/**
 * @param {d3.D3DragEvent} event
 * @param {BasicD3ManagmentItem} manager
 * @param {NetlistRender} rootRender 
 */
function dragEnd(event, manager, rootRender) {
    const selection = manager.selection;
    selection.attr('class', 'grab');
}