<script>
let Node = {
    Create:(inID, inDisplay, inChildren)=>
    {
        let node = {
            ID:inID,
            Display:inDisplay,
            Active:false,
            Highlighted:0,
            Parent:false,
            Children:inChildren,
            Leaves:[]
        };
        if(inChildren)
        {
            inChildren.forEach(c=>c.Parent = node);
        }
        return node;
    },
    Path:(inNode, inList) =>
    {
        let node = inNode;
        while(node)
        {
            inList.push(node);
            node = node.Parent;
        }
    },
    Leaves:(inNode, inList) =>
    {
        var i;
        var child;
        if(inNode.Children)
        {
            for(i=0; i<inNode.Children.length; i++)
            {
                Node.Decedents(inNode.Children[i], inList);
            }
        }
        else
        {
            inList.push(inNode);
        }
    }
};
</script>

<div id="root"></div>
<script type="module">

import _ from "https://dev.jspm.io/lodash";
import React from "https://dev.jspm.io/react/index.js";
import ReactDOM from "https://dev.jspm.io/react-dom/index.js";
import ReactDOMServer from "https://dev.jspm.io/react-dom/server.js";

let Util = {
    ParsePassage:inRef=>
    {
        let indexNumeric = inRef.lastIndexOf(" ");
        let partBook = inRef.substring(0, indexNumeric);
        let chapterVerse = inRef.substring(indexNumeric+1).split(":");
        return [partBook, chapterVerse[0], chapterVerse[1]];
    }
};

let h = React.createElement;

let ElemApp = props =>
{
    return h("div", null,
    [
        h(ElemTreeNode, {key:"tree", node:App.State.Tree.Root}),
        h("h4", {key:0}, "topics"),
        h(ElemTopics, {key:1}),
        h(ElemItems, {key:3})
    ]
    );
};

let ElemItems = props =>
{
    let list = App.State.Pages.All[App.State.Pages.Active].map( i=>h(ElemItem, {...i, key:i.id} ) );

    let pages = h(ElemPager, {count:App.State.Pages.All.length, active:App.State.Pages.Active}, null);

    return h("div", null, [
        h("h4", {key:0}, App.State.Items.Active.length+" results"),
        h("div", {key:1}, pages),
        h("div", {key:2}, list),
        h("div", {key:3}, pages)
    ]);
}
let ElemItem = props =>
{
    return h("div", {key:0}, [
        h("div", {key:1},
        [
            h("span", {key:0}, props.title),
            h("em", {key:1}, props.id)
        ]
        ),
        h("small", {key:3}, props.bible)
    ])
};
let ElemPager = ({count, active}) =>
{
    var children;
    var blockIntro, blockAt, blockOutro;
    var hitLeft, hitRight;

    let renderRange = (inStart, inStop) =>
    {
        let output = [];
        for(let i=inStart; i<=inStop; i++)
        {
            output.push(h("button", {key:i, onClick:e=>App.Update.Page(i)}, i+1));
        }
        return output;
    }
    let renderSpacer = () => h("span", {key:Math.random()}, "…");


    blockIntro = [0, 1, 2];
    blockAt = [active-1, active, active+1];
    blockOutro = [count-3, count-2, count-1];

    hitLeft = _.last(blockIntro) >= _.head(blockAt);
    hitRight = _.last(blockAt) >= _.head(blockOutro);

    if(count < 2)
    {
        children = [];
    }
    else
    {
        if( (hitLeft && hitRight) || count < 7)
        {
            children = renderRange(_.head(blockIntro), _.last(blockOutro)) /* merge all */
        }
        else if(!hitLeft && hitRight)
        {
            children = [
                ...renderRange(_.head(blockIntro), _.last(blockIntro)),
                renderSpacer(),
                ...renderRange(Math.min(_.head(blockAt), _.head(blockOutro)), _.last(blockOutro)) /* merge end */
            ];
        }
        else if(hitLeft && !hitRight)
        {
            children = [
                ...renderRange(_.head(blockIntro), Math.max(_.last(blockAt), _.last(blockIntro)) ), /* merge beginning */
                renderSpacer(),
                ...renderRange(_.head(blockOutro), _.last(blockOutro))
            ];
        }
        else if(!hitLeft && !hitRight)
        {
            children = [
                ...renderRange(_.head(blockIntro), _.last(blockIntro)),
                renderSpacer(),
                ...renderRange(_.head(blockAt), _.last(blockAt)),
                renderSpacer(),
                ...renderRange(_.head(blockOutro), _.last(blockOutro))
            ];
        }

    }

    return h("div", {}, children);
};

let ElemTopics = props =>
{
    let children = App.State.Topics.All.map( t=>
    {
        return h(ElemTopic, {
            onClick:e=>App.Update.Topic(t),
            key:t.id,
            label:t.display, 
            active:t.active
        });
    });
    return h("div", null, children);
};
let ElemTopic = props =>
{
    let label = props.active? props.label+" !" : props.label;
    return h("button", {onClick:props.onClick}, label);
};

let ElemTreeNode = ({node}) =>
{
    let children = [];
    if(node.Children)
    {
        children = node.Children.map( c=>h(ElemTreeNode, {node:c, key:c.ID}));
    }
    
    return h("div", {style:{padding:"10px"}}, [
        h("strong", {
            onClick:e=>
            {
                e.stopPropagation();
                App.Update.Select(App.State.Tree, node);
            },
            style:
            {
                background:node.Highlighted?"red":"none"
            }
        }, node.Display),
        h("div", {}, children)
    ]);
};

var App = {
    State:
    {
        Items:
        {
            All:[],
            Active:[]
        },
        Pages:
        {
            All:[],
            Active:0,
        },
        Tree:
        {
            Active:false,
            Highlighted:false,
            Root:
            Node.Create("root", "Root", [
                Node.Create("b1", "Branch 1", [
                    Node.Create("l1", "Leaf One")
                ]),
                Node.Create("b2", "Branch 2", [
                    Node.Create("l2", "Leaf Two"),
                    Node.Create("l3", "Leaf Three"),
                ])
            ])
        },
        Topics:
        {
            All:
            [
                {
                    id:"gospel-the",
                    display:"The Gospel",
                    active:false,
                    members:[]
                },
                {
                    id:"jesus-christ",
                    display:"Jesus Christ",
                    active:false,
                    members:[]
                },
                {
                    id:"biblical-figures",
                    display:"Biblical Figures",
                    active:false,
                    members:[]
                },
                {
                    id:"free-will",
                    display:"Free Will",
                    active:false,
                    members:[]
                },
                {
                    id:"secular-culture",
                    display:"Secular Culture",
                    active:false,
                    members:[]
                }
            ],
            Active:[]
        },
        Scripture:
        {
            All:{},
            Active:[]
        }
    },

    RootDOM:document.querySelector("#root"),
    RootComponent:ElemApp,
    Render:()=>ReactDOM.render( h(App.RootComponent), App.RootDOM ),
    ApplyFilters:()=>
    {
        if(App.State.Topics.Active.length == 0)
        {
            App.State.Items.Active = [...App.State.Items.All];
        }
        else
        {
            App.State.Items.Active = App.State.Items.All.filter( item =>
            {
                for(let i=0; i<item.topics.length; i++)
                {
                    for(let j=0; j<App.State.Topics.Active.length; j++)
                    {
                        if(item.topics[i] == App.State.Topics.Active[j].id)
                        {
                            return true;
                        }
                    }
                }
                return false;
            });
        }
        App.State.Pages.All = _.chunk(App.State.Items.Active, 10);
        App.State.Pages.Active = 0;
    },

    Update:
    {
        Select:(inTree, inNode)=>
        {
            if(inNode.Active)
            {
                inNode.Active = false;
                inTree.Highlighted.forEach( h=>h.Highlighted-- );

                inTree.Root.Active = true;
                inTree.Root.Highlighted = true;
                
                inTree.Active = inTree.Root;
                inTree.Highlighted = [inTree.Root];
            }
            else
            {
                if(inTree.Active)
                {
                    inTree.Active.Active = false;
                    inTree.Highlighted.forEach( h=>h.Highlighted-- );
                }

                inTree.Active = inNode;
                inTree.Active.Active = true;
                inTree.Highlighted = [];
                Node.Path(inTree.Active, inTree.Highlighted);
                inTree.Highlighted.forEach( h=>h.Highlighted++ );
            }
            console.log(inTree);
            App.Render();
        },
        Load:(file)=>
        {
            fetch(file)
                .then(inAccept=>inAccept.text())
                .then(inAccept=>
                {
                    let columns = inAccept.split("|");
                    App.State.Items.All = [];
                    for(let i=0; i<columns.length; i+=4)
                    {
                        let row = Math.floor(i/4);
                        App.State.Items.All[row] = {
                            title:columns[i+0],
                            id:columns[i+1],
                            bible:columns[i+2].split("*"),
                            topics:columns[i+3].split("*")
                        };
                    }
                    App.ApplyFilters();
                    App.Render();
                }
            );
        },
        Topic:(topic)=>
        {
            if(topic.active)
            {
                topic.active = false;
                App.State.Topics.Active = App.State.Topics.Active.filter( t=>t.id != topic.id );
            }
            else
            {
                topic.active = true;
                App.State.Topics.Active.push(topic);
            }
            App.ApplyFilters();
            App.Render();
        },
        Page:(page)=>
        {
            if(page !== false)
            {
                App.State.Pages.Active = page;
                App.Render();
            }
        }
    }
};

App.Update.Load("data-flat.csv");

</script>