<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1"/>
    <script src="./libraries/papaparse.min.js"></script>
    <script src="./libraries/n.js"></script>
    <script src="./libraries/pivot.js"></script>
    <script src="./data/csv.js"></script>
</head>
<body>
    <div id="app"></div>
    <!-- initialize table -->
    <script>
    let columnNames = CSV.shift();
    let columnTypes = ([...columnNames]).fill("hidden");
    columnTypes[29] = "sum";
    columnTypes[30] = "sum";
    columnTypes[31] = "sum";
    columnTypes[32] = "sum";
    columnTypes[33] = "sum";
    columnTypes[7 ] = "label";
    columnTypes[8 ] = "label";
    columnTypes[9 ] = "label";
    columnTypes[10] = "label";
    columnTypes[11] = "label";
    Pivot.Init(
        columnTypes,
        columnNames,
        CSV
    );
    </script>
    <!-- rendering -->
    <script type="module">
    import { h, render, createContext, Fragment } from 'https://cdn.skypack.dev/preact';
    import { useReducer, useState } from 'https://cdn.skypack.dev/preact/hooks';
    import { css, cx } from 'https://cdn.skypack.dev/@emotion/css';
    import htm from 'https://unpkg.com/htm?module';
    const html = htm.bind(h);
    
    let PivotForm = props =>
    {
        let styles = css`
            position:realtive;
            box-sizing: border-box;
            padding: 10px;
            color:black;
            font-family:sans-serif;
    
            .Title
            {
                font-size:24px;
                font-weight:100;
            }
    
            .Section
            {
                padding:10px 0 10px 0;
    
                .Heading
                {
                    display:inline-block;
                    color:#666;
                    font-family:sans-serif;
                    font-size:12px;
                    font-weight:900;
                    text-transform:uppercase;
                }
                .Group
                {
                    display:inline-block;
                    padding:5px;
                    border-radius:5px;
                    margin:3px;
                    background:rgba(0, 0, 0, 0.3)
                }
            }
        `;
    
    
        let pivotColumns = N.Step(Pivot.Schema, "label")||[];
        let pivotColumnsUsed = N.Step(Pivot.Proto, "used-pivot")||[];
    
        let sumColumns = N.Step(Pivot.Schema, "sum")||[];
        //let sumColumnsUsed = N.Step(Pivot.Proto, "used-sum")||[];
    
        let indiciesPivot = pivotColumnsUsed.map(node=>node.Meta.Index);
        let indiciesSum = sumColumns.map(node=>node.Meta.Index);
        //let indiciesSum = sumColumnsUsed.map(node=>node.Meta.Index);
        
        let displayPivotsAll = html`
        <div class="Section">
            <div class="Heading">Available Columns</div>
            <div class="Group">
            ${pivotColumns.map( columnPivot =>
            {
                let attributes = {};
                if(N.Step(columnPivot, "used-pivot", false))
                {
                    attributes.disabled = true;
                }
                else
                {
                    attributes.onClick = e=>
                    {
                        N.Connect(Pivot.Proto, columnPivot, "used-pivot");
                        Render();
                    }
                }
                return html`<button ...${attributes}>${columnPivot.Meta.Label}</button>`;
            })}
            </div>
        </div>
        `;
    
        let displayPivotsPending = null;
        if(pivotColumnsUsed.length)
        {
            displayPivotsPending  = html`
            <div class="Section">
                <div class="Heading">Pending Pivot</div>
                <div class="Group">
                    ${pivotColumnsUsed.map(columnPivot=>html`
                    <button onClick=${e=>{N.Disconnect(Pivot.Proto, columnPivot, "used-pivot");Render();}}>
                        ${columnPivot.Meta.Label}
                    </button>
                    `)}
                </div>
    
                <button onClick=${e=>{
                    N.Disconnect(Pivot.Proto, null, "used-pivot");
                    N.Disconnect(Pivot.Proto, null, "used-sum");
                    Pivot.Create(pivotColumnsUsed.map(column=>column.Meta.Label).join("|"), indiciesPivot, indiciesSum);
                    Render();
                }}>Create</button>
            </div>
            `;
        }
    
        return html`
        <div class=${styles}>
            <div class="Title">Create New Pivot</div>
            ${displayPivotsAll}
            ${displayPivotsPending}
        </div>
        `;
    }
    
    let Section = props =>
    {
        let styles = css`
            .Heading
            {
                padding:6px 0 6px 0;
                color:#666;
                font-weight:900;
                font-size:12px;
                text-transform:uppercase;
                cursor:pointer;
    
                span
                {
                    display:inline-block;
                    width:20px;
                    height:20px;
                    margin-right:10px;
                    border-radius:20px;
                    background:black;
                    color:white;
                    text-align:center;
                }
            }
            .Heading:hover
            {
                color:black;
            }
            .Body
            {
                position:relative;
                padding:10px 0 20px 30px;
                &::before
                {
                    content: " ";
                    display:block;
                    position:absolute;
                    top:-8px;
                    left:8px;
                    width:3px;
                    height:100%;
                    background:black;
                }
            }
        `;
    
        let [openGet, openSet] = useState(false);
        return html`
            <div class=${styles}>
                <div class="Heading" onClick=${e=>openSet(!openGet)}>
                    <span>${openGet ? `−` : `+`}</span>
                    ${props.label}
                </div>
                ${ openGet ? html`<div class="Body">${props.children}</div>` : null }
            </div>
        `;
    }
    
    let ModificationsIcon = ({node}) =>
    {
        let modsUp   = N.Step(node, "ModifyUp",   false)||[];
        let modsDown = N.Step(node, "ModifyDown", false)||[];
        let modsAt   = N.Step(node, "ModifyAt",   false)||[];
        let modsOut  = N.Step(node, "ModifyOut",  false)||[];
    
        var button = null;
        if(modsAt.length)
        {
            button = html`<button onClick=${e=>{Pivot.Unmodify(modsAt[0]); Render();}}>-</button>`;
        } 
        else
        {
            button = html`<button onClick=${e=>{Pivot.Modify(node); Render();}}>+</button>`;
        }
    
        let padding = 7;
        let icon = 0;
        let styles = css`
            position:relative;
            display:inline-block;
            vertical-align:middle;
            width:${padding*2 + icon}px;
            height:${padding*2 + icon}px;
            margin:${padding*2};
            .Icon
            {
                position:absolute;
                display:inline-block;
                width:${padding*2 + icon}px;
                height:${padding*2 + icon}px;
                text-align:center;
                font-size:9px;
                font-family:sans-serif;
                font-weight:900;
                line-height:${padding*2 + icon}px;
    
                &::after
                {
                    content:" ";
                    display:block;
                    position:absolute;
                    width:${icon}px;
                    height:${icon}px;
                    border:${padding}px solid transparent;
                }
    
                &.Down
                {
                    left:0;
                    bottom:100%;
                    &::after
                    {
                        top:100%;
                        border-top-color:green;
                        border-bottom:0px solid transparent;
                    }
                }
                &.At
                {
                    top:0;
                    left:100%;
                    &::after
                    {
                        top:0;
                        right:100%;
                        border-right-color:red;
                        border-left:0px solid transparent;
                    }
                }
                &.Up
                {
                    left:0;
                    top:100%;
                    &::after
                    {
                        bottom:100%;
                        border-bottom-color:orange;
                        border-top:0px solid transparent;
                    }
                }
    
                &.Out
                {
                    top:0;
                    right:100%;
                    &::after
                    {
                        top:0;
                        left:100%;
                        border-left-color:grey;
                        border-right:0px solid transparent;
                    }
                }
            }
    
        `;
    
        return html`
        <div class=${styles}>
            ${modsDown.length ? html`<div class="Icon Down">${modsDown.length}</div>` : null}
            ${modsAt.length ? html`<span class="Icon At">${modsAt.length}</span>` : null}
            ${modsUp.length ? html`<span class="Icon Up">${modsUp.length}</span>` : null}
            ${modsOut.length ? html`<span class="Icon Out">${modsOut.length}</span>` : null}
        </div>
        ${button}
        `;
    
    };
    
    let PivotBranch = props =>
    {
        let row = props.node.Meta.Row;
        let displayCellsModify = row.map(column=>false);
        props.node.Meta.IndexSum.forEach(i=>
        {
            displayCellsModify[i] = html`<td><input type="number" value=${row[i]}/></td>`;
        });
        displayCellsModify.forEach((cell, i)=>
        {
            if(!cell)
            {
                displayCellsModify[i] = html`<td>${row[i]}</td>`
            }
        });
    
        let displayCells = (node, visible) =>
        {
            let output = [];
            node.Meta.Row.forEach((column, i)=>
            {
                if(visible[i])
                {
                    output.push( h("td", null, column) );
                }
            }
            );
            return output;
        }
    
        let stylesLeaf = css`
            background:#ddd;
            color:#333;
        `;
    
        return html`
        <tbody>
            <tr>
                <td>
                    <strong class=${css`margin-left:${props.node.Meta.Depth*10}px;`}>${props.node.Meta.Label}</strong>
                </td>
                <td>
                    <${ModificationsIcon} node=${props.node}><//>
                </td>
                ${displayCells(props.node, props.visible)}
            </tr>
            ${(N.Step(props.node, "Leaf")||[]).map(leaf =>
            {
                return html`
                <tr class=${stylesLeaf}>
                    <td></td>
                    <td><${ModificationsIcon} node=${leaf}><//></td>
                    ${displayCells(leaf, props.visible)}
                </tr>
                `;
            }
            )}
        </tbody>
        `;
    };
    
    let PivotRoot = ({pivot}) =>
    {
        let labelsDefault = (N.Step(Pivot.Schema, "hidden")||[]).map(column => column.Meta.Index);
        let labelsSum = (N.Step(Pivot.Schema, "sum")||[]).map(column => column.Meta.Index);
        let labelsPivot = (N.Step(Pivot.Schema, "label")||[]).map(column => column.Meta.Index);
        let labelsAll = (N.Step(Pivot.Schema, "all")||[]).map(column => column.Meta.Label);
        let labelsAllState = useState(labelsAll.map(column=>true));
    
        let headersDisplay = [];
        labelsAllState[0].forEach((visible, index)=>
        {
            if(visible)
            {
                headersDisplay.push(html`<th>${labelsAll[index]}</th>`);
            }
        }
        );
    
        let stylesRoot = css`
            display:block;
            box-sizing:border-box;
            padding:15px;
            font-family:sans-serif;
        `;
        let stylesHeading = css`
            margin: 0 0 15px 0;
            font-weight:0;
            font-size:24px;
        `;
    
        let modifiers = N.Step(pivot, "ModifyUp", false) || [];
        let handleDelete = ()=>
        {
            Pivot.Delete(pivot);
            Render();
        };
    
    
        let displayColumnGroup = (inAllLabels, inAllState, inIndicies) =>
        {
            return html`
            <div>
                <button onClick=${e=>
                {
                    let clone = [...inAllState[0]];
                    inIndicies.forEach(index =>clone[index] = true);
                    inAllState[1](clone);
                }
                }>Show All</button>
                <button onClick=${e=>
                {
                    let clone = [...inAllState[0]];
                    inIndicies.forEach(index =>clone[index] = false);
                    inAllState[1](clone);
                }
                }>Hide All</button>
            </div>
            <div>
                ${inIndicies.map((index) => html`<button onClick=${e=>
                {
                    let clone = [...inAllState[0]];
                    clone[index] = !clone[index];
                    inAllState[1](clone);
                }
                }>${inAllLabels[index]} ${inAllState[0][index] ? `visible`:`hidden`}</button>`)}
            </div>`;
        };
    
        let rows = [];
        N.ID.Walk++;
        N.Walk(n=>rows.push(h(PivotBranch, {node:n, visible:labelsAllState[0]}, null)), pivot, "Hierarchy");
    
        return html`
        <div class=${stylesRoot}>
            <div key="heading" class=${stylesHeading}>${pivot.Meta.Label}</div>
            <${Section} key="settings" label=${`Settings`}>
                <button onClick=${handleDelete}>Destroy Pivot</button>
            <//>
            <${Section} key="columns" label="Columns">
                <h3>Unused</h3>
                ${displayColumnGroup(labelsAll, labelsAllState, labelsDefault)}
                <h3>Summation</h3>
                ${displayColumnGroup(labelsAll, labelsAllState, labelsSum)}
                <h3>Pivot</h3>
                ${displayColumnGroup(labelsAll, labelsAllState, labelsPivot)}
            <//>
            <${Section} key="tree" label=${"Tree"}>
                <table>
                    <thead>
                        <tr>
                            <th>Label</th><th>Modifications</th>${headersDisplay}
                        </th>
                    </thead>
                    ${rows}
                </table>
            <//>
        </div>
        `;
    };
    
    let ElRoot = props =>
    {
        let pivots = N.Step(Pivot.Root, "Pivot")||[];
        return h("div", null, [
            h(PivotForm),
            pivots.map(pivot=>h(PivotRoot, {key:pivot.Meta.Label, pivot}))
        ])
    };
    const Render = () => render(h(ElRoot), document.querySelector("#app"));
    Render();
    
    </script>
</body>
</html>