import * as d3 from './d3-custom';
import { round, typeset } from './utilities';

export function createScrollView(options) {

    // dimensions
    let offset;
    let boundingBox;
    let barHeight;   // height of bar in maximum (visible) scale

    let colours;
    let font;
    let lang;

    let transitionDuration;
    let category = '';
    let entries;
    let digits = 2;

    // svg element
    let entriesGroup;

    let controller;


    function scrollView(selection) {

        entriesGroup = selection.append('g')
            .attr('class', 'entries');
    }

    scrollView.update = function(newData) {

        // >>> UPDATE >>>
        var urow = entriesGroup.selectAll('g.entry');
        urow.exit().remove();

        if(newData) {  // only when selection changed... update with transitions
            urow.each(function() {  // tween text: animate numbers
                d3.select(this).select('text.vtxt')
                    .transition().duration(transitionDuration)
                    .tween('text', function(d) {
                        var node = this;
                        var i = d3.interpolateNumber(d.previousValue, d.value);

                        return function(t) {
                            node.textContent = typeset(round(i(t))) + ' ' + d.reason.referenceGroup;
                        };
                    });
                d3.select(this).select('.selectable')
                    .on('click', function(e, d) { 
                        controller.toggleSelection(d);
                        let col = d.selected ? colours.highlight : colours.translucent;
                        d3.select(this).attr('fill',col);
                    })
                    .on('mouseover', function() { d3.select(this).attr('fill', colours.highlight); })
                    .on('mouseout', function(e, d) {
                        let col = d.selected ? colours.highlight : colours.translucent;
                        d3.select(this).attr('fill',col);
                    });
            });

            urow.transition()  // (chained is problematic) transition: fade in / out, then translate
                .duration(100)
                .attr('opacity', function(d) {  // fade entries in / out
                    if(d.y > boundingBox.height - barHeight) {
                        return 0.0;
                    }
                    if(category !== '' && category !== d.reason.cat) {
                        return 0.0;
                    }
                    return 1.0;
                })
                .transition()
                .duration(transitionDuration)
                .attr('transform', function(d) {
                    console.log(d, boundingBox);
                    return 'translate(' + (d.x + boundingBox.min.x) + ',' + (d.y + boundingBox.min.y) + ') scale(' + d.ratio + ',' + d.ratio + ')';
                })
                .on('end', function() {
                    controller.dataProcessed();  // this should be the last transition to finish!
                });

            urow.sort(function(a, b) {  // update the drawing order of the svg elements
                return a.y - b.y;
            });

        } else {  // adjustments on scroll (transitions only take place when elements leave / enter the 'view frustum')
            urow.attr('transform', function(d) {
                return 'translate(' + (d.x + boundingBox.min.x) + ',' + (d.y + boundingBox.min.y) + ') scale(' + d.ratio + ',' + d.ratio + ')'; 
            });
            urow.each(function() {  // adjust on scroll
                d3.select(this).select('rect.clickable')
                    .attr('width', boundingBox.width)
                    .attr('height', barHeight);
                d3.select(this).select('rect.value-bar')
                    .attr('width', function(d) { return boundingBox.width * d.value / 100000; })
                    .attr('height', barHeight)
                    .attr('stroke-dasharray', function(d) {  // only draw top, bottom, and left sides of rect
                        let wdth = boundingBox.width * d.value / 100000;
                        return wdth + ' ' + barHeight + ' ' + (wdth + barHeight);
                    });
                d3.select(this).select('.vlabel')
                    .attr('transform', 'translate(' + boundingBox.width + ',0)');

                d3.select(this).select('.selectable')
                    .attr('fill', function(d) { return d.selected ? colours.highlight : colours.translucent; });
                d3.select(this).select('rect.vbg')
                    .attr('height', barHeight)
                    .attr('fill', colours.translucent)
                    .attr('width', 14 * font.ratio.large * font.baseSize);
            });
            urow
                .attr('visibility', function(d) {
                    if(d.y > boundingBox.height - barHeight) {
                        return 'hidden';
                    }
                    if(category !== '' && category !== d.reason.cat) {
                        return 'hidden';
                    }
                    return 'visible';
                });
        }
        // <<< UPDATE <<<

        // >>> CREATE new entries >>>
        var row = entriesGroup.selectAll('g.entry')
            .data(entries, function(d) {
                return d.reason.title; });  // use title as key

        var entry = row.enter()
            .append('g')                                                    // entry group
            .attr('class', 'entry')
            .attr('id', function(d, i) { return 'entry-' + i; })
            .attr('transform', function(d) {
                return 'translate(' + d.x + ',' + (d.y + boundingBox.min.y) + ') scale(' + d.ratio + ',' + d.ratio + ')';
            });

        entry.append('rect')                                                // clickable rect
            .attr('class', 'clickable')
            .attr('fill', '#ccc')
            .attr('stroke', function (d) { return d.reason.colorFill; })
            .on('click', function(event, d) { controller.showInfo(d); });

        entry.append('rect')                                                // value bar
            .attr('class', 'value-bar clickable')
            .attr('id', function(d, i){ return 'node' + i; })
            .attr('fill', function(d) { return d.reason.colorFill; })
            .attr('stroke', function (d) { return d.reason.colorFill.brighter(); })
            .on('click', function(event, d) { controller.showInfo(d); });

        entry.append('clipPath')                                            // clip path for on-bar text
            .attr('id', function(d, i) { return 'clip-node' + i; })
            .append('use')
            .attr('xlink:href', function(d, i) { return '#node' + i; });

        entry.append('text')                                                // title label
            .attr('class', 'title')
            .attr('x', offset.x)
            .attr('y', barHeight / 2 + offset.y)
            .attr('fill', colours.text)
            .text(function(d) { return d.reason.title; });

        entry.append('text')                                                // title label
            .attr('class', 'title')
            .attr('x', offset.x)
            .attr('y', barHeight / 2 + offset.y)
            .attr('fill', colours.bright)
            .attr('clip-path', function(d, i) { return 'url(#clip-node' + i + ')'; })
            .text(function(d) { return d.reason.title; });

        entry.append('use')                                                 // bookmark icon
            .attr('xlink:href', '#bookmark')
            .attr('transform', 'translate(' + (boundingBox.width - font.ratio.large * font.baseSize) + ',-0.5)')
            .attr('width', font.ratio.medium * font.baseSize)
            .attr('height', font.ratio.medium * font.baseSize)
            .attr('stroke', colours.bright)
            .attr('stroke-width', 0.4)
            .attr('fill', function(d) { return d.selected ? colours.highlight : colours.translucent; })
            .attr('class', 'bookmark clickable selectable')
            .on('click', function(e, d) { controller.toggleSelection(d); })
            .on('mouseover', function() {
                d3.select(this).attr('fill', colours.highlight);
            })
            .on('mouseout', function(e, d) {
                let col = d.selected ? colours.highlight : colours.translucent;
                d3.select(this).attr('fill',col);
            });

        var vlabel = entry.append('g')                                      // value label group
            .attr('class', 'vlabel');

        vlabel.append('rect')                                                // value background
            .attr('class', 'vbg');

        vlabel.append('text')                                                // value label
            .attr('class', 'vtxt')
            .attr('x', offset.x)
            .attr('y', barHeight / 2 + offset.y)
            .attr('fill', colours.text)
            .text(function(d) { return typeset(round(d.value), lang) + ' ' + d.reason.referenceGroup; });
        // <<< CREATE <<<
    };

    scrollView.controller = function(val) {
        if(!arguments.length) {
            return controller;
        }
        controller = val;
        return scrollView;
    };

    scrollView.offset = function(val) {
        if(!arguments.length) {
            return offset;
        }
        offset = val;
        return scrollView;
    };

    scrollView.entries = function(val) {
        if(!arguments.length) {
            return entries;
        }
        entries = val;
        return scrollView;
    };

    // colours >>>
    scrollView.colours = function(obj) {
        if(!arguments.length) {
            return colours;
        }
        colours = obj;
        return scrollView;
    };

    scrollView.category = function(val) {
        if(!arguments.length) {
            return category;
        }
        category = val;
        return scrollView;
    };

    scrollView.lang = function(val) {
        if(!arguments.length) {
            return lang;
        }
        lang = val;
        return scrollView;
    };

    scrollView.boundingBox = function(val) {
        if(!arguments.length) {
            return boundingBox;
        }
        boundingBox = val;
        return scrollView;
    };

    scrollView.barHeight = function(val) {
        if(!arguments.length) {
            return barHeight;
        }
        barHeight = val;
        return scrollView;
    };

    scrollView.transitionDuration = function(val) {
        if(!arguments.length) {
            return transitionDuration;
        }
        transitionDuration = val;
        return scrollView;
    };

    scrollView.font = function(val) {
        if(!arguments.length) {
            return font;
        }
        font = val;
        return scrollView;
    };

    scrollView.digits = function(val) {
        if(!arguments.length) {
            return digits;
        }
        digits = val;
        return scrollView;
    };

    scrollView.controller(options.common.controller);
    scrollView.colours(options.common.colours);
    scrollView.font(options.common.font);
    scrollView.barHeight(options.barHeight);
    scrollView.boundingBox(options.boundingBox);
    scrollView.offset(options.offset);
    return scrollView;
}
