'use strict';

var scatterAttrs = require('../scatter/attributes');
var colorScaleAttrs = require('../../components/colorscale/attributes');
var axisHoverFormat = require('../../plots/cartesian/axis_format_attributes').axisHoverFormat;
var hovertemplateAttrs = require('../../plots/template_attributes').hovertemplateAttrs;
var scatterGlAttrs = require('../scattergl/attributes');
var cartesianIdRegex = require('../../plots/cartesian/constants').idRegex;
var templatedArray = require('../../plot_api/plot_template').templatedArray;
var extendFlat = require('../../lib/extend').extendFlat;

var scatterMarkerAttrs = scatterAttrs.marker;
var scatterMarkerLineAttrs = scatterMarkerAttrs.line;

var markerLineAttrs = extendFlat(colorScaleAttrs('marker.line', {editTypeOverride: 'calc'}), {
    width: extendFlat({}, scatterMarkerLineAttrs.width, {editType: 'calc'}),
    editType: 'calc'
});

var markerAttrs = extendFlat(colorScaleAttrs('marker'), {
    symbol: scatterMarkerAttrs.symbol,
    angle: scatterMarkerAttrs.angle,
    size: extendFlat({}, scatterMarkerAttrs.size, {editType: 'markerSize'}),
    sizeref: scatterMarkerAttrs.sizeref,
    sizemin: scatterMarkerAttrs.sizemin,
    sizemode: scatterMarkerAttrs.sizemode,
    opacity: scatterMarkerAttrs.opacity,
    colorbar: scatterMarkerAttrs.colorbar,
    line: markerLineAttrs,
    editType: 'calc'
});

markerAttrs.color.editType = markerAttrs.cmin.editType = markerAttrs.cmax.editType = 'style';

function makeAxesValObject(axLetter) {
    return {
        valType: 'info_array',
        freeLength: true,
        editType: 'calc',
        items: {
            valType: 'subplotid',
            regex: cartesianIdRegex[axLetter],
            editType: 'plot'
        },
        description: [
            'Sets the list of ' + axLetter + ' axes',
            'corresponding to dimensions of this splom trace.',
            'By default, a splom will match the first N ' + axLetter + 'axes',
            'where N is the number of input dimensions.',
            'Note that, in case where `diagonal.visible` is false and `showupperhalf`',
            'or `showlowerhalf` is false, this splom trace will generate',
            'one less x-axis and one less y-axis.',
        ].join(' ')
    };
}

module.exports = {
    dimensions: templatedArray('dimension', {
        visible: {
            valType: 'boolean',
            dflt: true,
            editType: 'calc',
            description: [
                'Determines whether or not this dimension is shown on the graph.',
                'Note that even visible false dimension contribute to the',
                'default grid generate by this splom trace.'
            ].join(' ')
        },
        label: {
            valType: 'string',
            editType: 'calc',
            description: 'Sets the label corresponding to this splom dimension.'
        },
        values: {
            valType: 'data_array',
            editType: 'calc+clearAxisTypes',
            description: 'Sets the dimension values to be plotted.'
        },

        axis: {
            type: {
                valType: 'enumerated',
                values: ['linear', 'log', 'date', 'category'],
                editType: 'calc+clearAxisTypes',
                description: [
                    'Sets the axis type for this dimension\'s generated',
                    'x and y axes.',
                    'Note that the axis `type` values set in layout take',
                    'precedence over this attribute.'
                ].join(' ')
            },

            // TODO make 'true' the default in v3?
            matches: {
                valType: 'boolean',
                dflt: false,
                editType: 'calc',
                description: [
                    'Determines whether or not the x & y axes generated by this',
                    'dimension match.',
                    'Equivalent to setting the `matches` axis attribute in the layout',
                    'with the correct axis id.'
                ].join(' ')
            },

            editType: 'calc+clearAxisTypes'
        },

        // TODO should add an attribute to pin down x only vars and y only vars
        // like https://seaborn.pydata.org/generated/seaborn.pairplot.html
        // x_vars and y_vars

        // maybe more axis defaulting option e.g. `showgrid: false`

        editType: 'calc+clearAxisTypes'
    }),

    // mode: {}, (only 'markers' for now)

    text: extendFlat({}, scatterGlAttrs.text, {
        description: [
            'Sets text elements associated with each (x,y) pair to appear on hover.',
            'If a single string, the same string appears over',
            'all the data points.',
            'If an array of string, the items are mapped in order to the',
            'this trace\'s (x,y) coordinates.'
        ].join(' ')
    }),
    hovertext: extendFlat({}, scatterGlAttrs.hovertext, {
        description: 'Same as `text`.'
    }),

    hovertemplate: hovertemplateAttrs(),

    xhoverformat: axisHoverFormat('x'),
    yhoverformat: axisHoverFormat('y'),

    marker: markerAttrs,

    xaxes: makeAxesValObject('x'),
    yaxes: makeAxesValObject('y'),

    diagonal: {
        visible: {
            valType: 'boolean',
            dflt: true,
            editType: 'calc',
            description: [
                'Determines whether or not subplots on the diagonal are displayed.'
            ].join(' ')
        },

        // type: 'scattergl' | 'histogram' | 'box' | 'violin'
        // ...
        // more options

        editType: 'calc'
    },

    showupperhalf: {
        valType: 'boolean',
        dflt: true,
        editType: 'calc',
        description: [
            'Determines whether or not subplots on the upper half',
            'from the diagonal are displayed.'
        ].join(' ')
    },
    showlowerhalf: {
        valType: 'boolean',
        dflt: true,
        editType: 'calc',
        description: [
            'Determines whether or not subplots on the lower half',
            'from the diagonal are displayed.'
        ].join(' ')
    },

    selected: {
        marker: scatterGlAttrs.selected.marker,
        editType: 'calc'
    },
    unselected: {
        marker: scatterGlAttrs.unselected.marker,
        editType: 'calc'
    },

    opacity: scatterGlAttrs.opacity
};
