"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Scatter = void 0;
/* Copyright 2015 Bloomberg Finance L.P.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const ScatterBase_1 = require("./ScatterBase");
const markers = __importStar(require("./Markers"));
const d3 = __importStar(require("d3"));
// const d3 =Object.assign({}, require("d3-selection"));
const bqSymbol = markers.symbol;
class Scatter extends ScatterBase_1.ScatterBase {
    render() {
        this.dot = bqSymbol()
            .type(this.model.get('marker'))
            .size(this.model.get('default_size'))
            .skew(this.model.get('default_skew'));
        return super.render();
    }
    create_listeners() {
        super.create_listeners();
        this.listenTo(this.model, 'change:colors', this.update_colors);
        this.listenTo(this.model, 'change:stroke', this.update_stroke);
        this.listenTo(this.model, 'change:stroke_width', this.update_stroke_width);
        this.listenTo(this.model, 'change:opacities', this.update_opacities);
        this.listenTo(this.model, 'change:default_skew', this.update_default_skew);
        this.listenTo(this.model, 'change:marker', this.update_marker);
        this.listenTo(this.model, 'change:default_size', this.update_default_size);
        this.listenTo(this.model, 'change:fill', this.update_fill);
        this.listenTo(this.model, 'change:display_names', this.update_names);
        this.listenTo(this.model, 'change:label_display_horizontal_offset change:label_display_vertical_offset', this.update_names);
    }
    update_colors(model, new_colors) {
        if (!this.model.dirty) {
            const stroke = this.model.get('stroke');
            const len = new_colors.length;
            this.d3el
                .selectAll('.dot')
                .style('fill', this.model.get('fill') ? this.get_mark_color.bind(this) : 'none')
                .style('stroke', stroke ? stroke : this.get_mark_color.bind(this));
            if (this.legend_el) {
                this.legend_el
                    .select('path')
                    .style('fill', (d, i) => {
                    return new_colors[i % len];
                })
                    .style('stroke', stroke
                    ? stroke
                    : (d, i) => {
                        return new_colors[i % len];
                    });
                this.legend_el.select('text').style('fill', this.model.get('fill')
                    ? (d, i) => {
                        return new_colors[i % len];
                    }
                    : 'none');
            }
        }
        this.apply_styles();
    }
    update_fill(model, fill) {
        const colors = this.model.get('colors');
        const len = colors.length;
        this.d3el
            .selectAll('.dot')
            .style('fill', fill ? this.get_mark_color.bind(this) : 'none');
        if (this.legend_el) {
            this.legend_el.selectAll('path').style('fill', fill
                ? (d, i) => {
                    return colors[i % len];
                }
                : 'none');
        }
    }
    update_stroke_width() {
        const stroke_width = this.model.get('stroke_width');
        this.d3el.selectAll('.dot').style('stroke-width', stroke_width);
        if (this.legend_el) {
            this.legend_el.selectAll('path').style('stroke-width', stroke_width);
        }
    }
    update_stroke(model, fill) {
        const stroke = this.model.get('stroke');
        this.d3el
            .selectAll('.dot')
            .style('stroke', stroke ? stroke : this.get_mark_color.bind(this));
        if (this.legend_el) {
            this.legend_el.selectAll('path').style('stroke', stroke);
        }
    }
    update_opacities(animate) {
        if (!this.model.dirty) {
            const opacities = this.model.get('opacities');
            const colors = this.model.get('colors');
            const len = colors.length;
            const len_opac = opacities.length;
            const animation_duration = animate === true ? this.parent.model.get('animation_duration') : 0;
            // update opacity scale range?
            const that = this;
            this.d3el
                .selectAll('.dot')
                .transition('update_opacities')
                .duration(animation_duration)
                .style('opacity', (d, i) => {
                return that.get_element_opacity(d, i);
            });
            if (this.legend_el) {
                this.legend_el
                    .select('path')
                    .style('opacity', (d, i) => {
                    return opacities[i % len_opac];
                })
                    .style('fill', (d, i) => {
                    return colors[i % len];
                });
            }
        }
    }
    update_marker(model, marker) {
        if (!this.model.dirty) {
            this.d3el
                .selectAll('.dot')
                .transition('update_marker')
                .duration(this.parent.model.get('animation_duration'))
                .attr('d', this.dot.type(marker));
            if (this.legend_el) {
                this.legend_el.select('path').attr('d', this.dot.type(marker));
            }
        }
    }
    update_default_skew(animate) {
        if (!this.model.dirty) {
            const animation_duration = animate === true ? this.parent.model.get('animation_duration') : 0;
            const that = this;
            this.d3el
                .selectAll('.dot')
                .transition('update_default_skew')
                .duration(animation_duration)
                .attr('d', this.dot.skew((d) => {
                return that.get_element_skew(d);
            }));
        }
    }
    update_default_size(animate) {
        this.compute_view_padding();
        // update size scale range?
        if (!this.model.dirty) {
            const animation_duration = animate === true ? this.parent.model.get('animation_duration') : 0;
            const that = this;
            this.d3el
                .selectAll('.dot')
                .transition('update_default_size')
                .duration(animation_duration)
                .attr('d', this.dot.size((d) => {
                return that.get_element_size(d);
            }));
            // Label positions also need to change
            this.update_names(animate);
        }
    }
    update_names(animate) {
        const that = this;
        const names = this.model.get('names') || [];
        const show_names = this.model.get('display_names') && names.length !== 0;
        const animation_duration = animate
            ? this.parent.model.get('animation_duration')
            : 0;
        this.d3el
            .selectAll('.object_grp')
            .select('text')
            .text((d) => {
            return d.name;
        })
            .transition('update_names')
            .duration(animation_duration)
            .attr('transform', (d) => {
            const label_display_horizontal_offset = that.model.get('label_display_horizontal_offset');
            const label_display_vertical_offset = that.model.get('label_display_vertical_offset');
            const text_loc = Math.sqrt(that.get_element_size(d)) / 2.0;
            return ('translate(' +
                (label_display_horizontal_offset
                    ? label_display_horizontal_offset
                    : text_loc) +
                ',' +
                (label_display_vertical_offset
                    ? -label_display_vertical_offset
                    : -text_loc) +
                ')');
        })
            .attr('display', (d) => {
            return show_names ? 'inline' : 'none';
        });
    }
    color_scale_updated(animate) {
        const fill = this.model.get('fill'), stroke = this.model.get('stroke');
        const animation_duration = animate === true ? this.parent.model.get('animation_duration') : 0;
        this.d3el
            .selectAll('.object_grp')
            .select('path')
            .transition('color_scale_updated')
            .duration(animation_duration)
            .style('fill', fill ? this.get_mark_color.bind(this) : 'none')
            .style('stroke', stroke ? stroke : this.get_mark_color.bind(this));
    }
    draw_elements(animate, elements_added) {
        const that = this;
        const animation_duration = animate === true ? this.parent.model.get('animation_duration') : 0;
        const elements = this.d3el.selectAll('.object_grp');
        elements_added.append('path').attr('class', 'dot element');
        elements_added.append('text').attr('class', 'dot_text');
        elements
            .select('path')
            .transition('draw_elements')
            .duration(animation_duration)
            .attr('d', this.dot
            .size((d) => {
            return that.get_element_size(d);
        })
            .skew((d) => {
            return that.get_element_skew(d);
        }));
        this.update_names(animate);
        this.apply_styles();
    }
    draw_legend_elements(elements_added, rect_dim) {
        const colors = this.model.get('colors'), len = colors.length, stroke = this.model.get('stroke');
        elements_added
            .append('path')
            .attr('transform', (d, i) => {
            return 'translate( ' + rect_dim / 2 + ', ' + rect_dim / 2 + ')';
        })
            .attr('d', this.dot.size(64))
            .style('fill', this.model.get('fill')
            ? (d, i) => {
                return colors[i % len];
            }
            : 'none')
            .style('stroke', stroke
            ? stroke
            : (d, i) => {
                return colors[i % len];
            });
    }
    set_default_style(indices) {
        // For all the elements with index in the list indices, the default
        // style is applied.
        if (!indices || indices.length === 0) {
            return;
        }
        const elements = this.d3el.selectAll('.element').filter((data, index) => {
            return indices.indexOf(index) !== -1;
        });
        const fill = this.model.get('fill'), stroke = this.model.get('stroke'), stroke_width = this.model.get('stroke_width'), that = this;
        elements
            .style('fill', fill ? this.get_mark_color.bind(this) : 'none')
            .style('stroke', stroke ? stroke : this.get_mark_color.bind(this))
            .style('opacity', (d, i) => {
            return that.get_element_opacity(d, i);
        })
            .style('stroke-width', stroke_width);
    }
    set_drag_style(d, i, dragged_node) {
        d3.select(dragged_node)
            .select('path')
            .classed('drag_scatter', true)
            .transition('set_drag_style')
            .attr('d', this.dot.size(5 * this.model.get('default_size')));
        const drag_color = this.model.get('drag_color');
        if (drag_color) {
            d3.select(dragged_node)
                .select('path')
                .style('fill', drag_color)
                .style('stroke', drag_color);
        }
    }
    reset_drag_style(d, i, dragged_node) {
        const stroke = this.model.get('stroke'), original_color = this.get_mark_color(d, i);
        d3.select(dragged_node)
            .select('path')
            .classed('drag_scatter', false)
            .transition('reset_drag_style')
            .attr('d', this.dot.size(this.get_element_size(d)));
        if (this.model.get('drag_color')) {
            d3.select(dragged_node)
                .select('path')
                .style('fill', original_color)
                .style('stroke', stroke ? stroke : original_color);
        }
    }
}
exports.Scatter = Scatter;
//# sourceMappingURL=Scatter.js.map