class ADC2019Board {
    constructor(selector) {
        this.container = $(selector);
        this.width = this.container.width();
        this.height = $(window).height();
        this.svg = d3.select(selector).append('svg');
        this.view = this.svg.append('g').attr('class', 'view');
        this.currentTransform = null;
        this.cubeResolution = 50;
        this._init();
        this._draw_slider();
    }
    get_board_list(selector){
        var _self = this;
        var container = $(selector);
        container.html("");
        $.ajax({
            url: '/api/boards',
            type: 'GET',
        }).done((data) => {
            var $board_list = container.append("
");
            for(var i=0; i" + data[i] + "");
            }
            if(data.indexOf(_self._get_hash()) >= 0){
                _self.draw(_self._get_hash());
            }
        }).fail((data) => {
            console.log("Error");
        });
    }
    draw(name){
        this._draw_init();
        this._get_board(name);
    }
    _get_hash(){
        return location.hash.replace("#", "");
    }
    _init(){
        var _self = this;
        if (this.currentTransform){
            this.view.attr('transform', this.currentTransform);
        }
        $(window).on('hashchange', () => {
            _self.draw(_self._get_hash());
        });
    }
    _get_board(name){
        $.ajax({
            url: '/api/board/' + name,
            type: 'GET',
        }).done((data) => {
            this._draw_grid(data.size[0], data.size[1]);
            this._draw_blocks(data.blocks);
        }).fail((data) => {
            console.log("Error");
        });
    }
    _draw_init(){
        this.view.selectAll("g").remove();
    }
    _draw_grid(x_cnt, y_cnt){
        let _width = x_cnt * this.cubeResolution;
        let _height = y_cnt * this.cubeResolution;
        this.view.append("g")
            .attr("class", "x axis")
            .selectAll("line")
            .data(d3.range(0, _width+1, this.cubeResolution))
            .enter().append("line")
            .attr("x1", function (d) { return d; })
            .attr("y1", 0)
            .attr("x2", function (d) { return d; })
            .attr("y2", _height)
            .attr("stroke", "#888");
        this.view.append("g")
            .attr("class", "y axis")
            .selectAll("line")
            .data(d3.range(0, _height+1, this.cubeResolution))
            .enter().append("line")
            .attr("x1", 0)
            .attr("y1", function (d) { return d; })
            .attr("x2", _width)
            .attr("y2", function (d) { return d; })
            .attr("stroke", "#888");
    }
    _draw_slider(){
        let _self = this;
        var zoom = d3.zoom()
            .scaleExtent([0.5, 5])
            .translateExtent([
                [-this.width * 2, -this.height * 2],
                [this.width * 2, this.height * 2]
                ])
            .on("zoom", zoomed);
        function zoomed() {
            this.currentTransform = d3.event.transform;
            _self.view.attr("transform", this.currentTransform);
            // this.slider.property("value", d3.event.scale);
        }
        function slided(d) {
            zoom.scaleTo(this.svg, d3.select(this).property("value"));
        }
        
        // var slider = d3.select("body").append("input")
        //     .datum({})
        //     .attr("type", "range")
        //     .attr("value", 1)
        //     .attr("min", zoom.scaleExtent()[0])
        //     .attr("max", zoom.scaleExtent()[1])
        //     .attr("step", (zoom.scaleExtent()[1] - zoom.scaleExtent()[0]) / 100)
        //     .on("input", slided);
        this.svg.call(zoom).on('dblclick.zoom', null);
    }
    _draw_blocks(blocks){
        let cubeResolution = this.cubeResolution;
        function snapToGrid(p, r) {
            return Math.round(p / r) * r;
        }
        function dragged(d) {
            var el = d3.select(this);
            var _x = parseInt(el.attr('data-x'), 10) + d3.event.x;
            var _y = parseInt(el.attr('data-y'), 10) + d3.event.y;
            el.attr("transform", (d) => {
                    return 'translate(' + snapToGrid(_x, cubeResolution) + ',' + snapToGrid(_y, cubeResolution) + ')'
                })
        }
        function dragended(d) {
            var el = d3.select(this).classed("dragging", false);
            var _x = parseInt(el.attr('data-x'), 10) + d3.event.x;
            var _y = parseInt(el.attr('data-y'), 10) + d3.event.y;
            d3.select(this)
                .attr('data-x', snapToGrid(_x, cubeResolution))
                .attr('data-y', snapToGrid(_y, cubeResolution));
        }
        function dragstarted(d) {
            var el = d3.select(this);
            el.raise().classed("dragging", true);
        }
        let colors = d3.schemeCategory10
        // Reference 
        // Grid: https://bl.ocks.org/ngminhtrung/7c5721a1504f3e29a36da9ddd9e5039b
        // Snap: https://bl.ocks.org/evanjmg/ea3e59e67b4256c8831d3fc80f71294b
        // Nested data structure: https://codeday.me/jp/qa/20190428/720184.html
        var itemContainer = this.view.selectAll("g.itemContainer")
            .data(blocks)
            .enter()
            .append('g')
            .attr('class', 'itemContainer')
            .attr("transform", (d) => 'translate(' + d.x + ',' + d.y + ')')
            .attr('data-x', (d) => d.x)
            .attr('data-y', (d) => d.y)
            .call(d3.drag()
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended));
        var cellContainer = itemContainer.append('g')
            .attr('class', 'cellContainer')
            .attr('data-color', (d, i) => colors[i])
            .attr('x', 0)
            .attr('y', 0)
        cellContainer.selectAll('g')
            .data((d) => d.cells)
            .enter()
            .append('rect')
            .attr('x', (d) => d[0] * this.cubeResolution)
            .attr('y', (d) => d[1] * this.cubeResolution)
            .attr('width', this.cubeResolution)
            .attr('height', this.cubeResolution)
            .attr('cursor', 'move')
            .attr('fill', (d, i, nodes) => {
                return d3.select(nodes[i].parentNode).attr('data-color');
            });
        cellContainer.selectAll('g')
            .data((d) => d.cells)
            .enter()
            .append('text')
            .attr('x', (d) => d[0] * this.cubeResolution + 0.5 * this.cubeResolution)
            .attr('y', (d) => d[1] * this.cubeResolution + 0.5 * this.cubeResolution)
            .attr('width', this.cubeResolution)
            .attr('height', this.cubeResolution)
            .attr('text-anchor', 'middle')
            .attr('fill', 'white')
            .attr('font-size', '20px')
            .attr('cursor', 'move')
            .text((d) => d[2]);
    }
}
$(function(){
    // const board = new ADC2019Board("#board-container");
    // board.get_board_list("#board-list-container");
    // // board.draw("Q001_10X10_b8_n11.txt");
    
    var show_question_status = function(qname){
        $.ajax({
            type: "GET",
            dataType: "html",
            url: "/template/question/" + qname,
        }).done((d) => {
            $("#status-container").empty();
            $("#status-container").html(d);
            // $("#status-container").find(".start-button").eq(0).click(function(){
            //     var qname = $(this).data("qname");
            //     pm.sendQuestion(qname);
            // });
            // $("#status-container").find(".stop-button").eq(0).click(function(){
            //     pm.sendStop();
            // });
            // $("#status-container").find(".save-button").eq(0).click(function(){
            //     var qname = $(this).data("qname");
            //     $.ajax({
            //         type: "POST",
            //         dataType: "json",
            //         url: "/save",
            //         data: {qname: qname}
            //     }).done((data) => {
            //         alert(data['status']);
            //     });
            // });
            // $("#status-container").find(".submit-button").eq(0).click(function(){
            //     var qname = $(this).data("qname");
            //     $.ajax({
            //         type: "POST",
            //         dataType: "json",
            //         url: "/adccli-put-a",
            //         data: {qname: qname}
            //     }).done((data) => {
            //         alert(data['message']);
            //     });
            // });
            // $(".answer-detail-row td").click(function(){
            //     var json_name = $(this).parent("tr").data("json");
            //     var qname = $(this).parent("tr").data("qname");
            //     var viewer_url = "/board-viewer#" + qname + "," + json_name
            //     window.open(viewer_url, "_blank");
            // })
        });
    }
    var refresh_questions = function(){
        $.ajax({
            type: "GET",
            dataType: "html",
            url: "/template/questions"
        }).done((d) => {
            $("#question-list-container").empty();
            $("#question-list-container").html(d);
            $(".question-row td").click(function(){
                var $tr = $(this).parent("tr.question-row");
                $(".question-row").removeClass("q-selected");
                $tr.addClass("q-selected");
                var qname = $tr.data("qname");
                // show_question_status(qname);
                location.hash = "#" + qname;
                return false;
            });
            var hash = location.hash.replace("#", "");
            if(hash != ""){
                $(".question-row[data-qname='" + hash + "']").addClass("q-selected");
            }
        });
    }
    
    $(window).on('hashchange', function(){
        var hash = location.hash.replace("#", "");
        if(hash == ""){
            // show_client_table();
        }else{
            show_question_status(hash);
        }
    }).trigger('hashchange');
    refresh_questions();
});