/**
 * echarts组件类： 坐标轴
 *
 * @desc echarts基于Canvas，纯Javascript图表库，提供直观，生动，可交互，可个性化定制的数据统计图表。
 * @author Kener (@Kener-林峰, kener.linfeng@gmail.com)
 *
 * 直角坐标系中坐标轴数组，数组中每一项代表一条横轴（纵轴）坐标轴。
 * 标准（1.0）中规定最多同时存在2条横轴和2条纵轴
 *    单条横轴时可指定安放于grid的底部（默认）或顶部，2条同时存在时则默认第一条安放于底部，第二天安放于顶部
 *    单条纵轴时可指定安放于grid的左侧（默认）或右侧，2条同时存在时则默认第一条安放于左侧，第二天安放于右侧。
 * 坐标轴有两种类型，类目型和数值型（区别详见axis）：
 *    横轴通常为类目型，但条形图时则横轴为数值型，散点图时则横纵均为数值型
 *    纵轴通常为数值型，但条形图时则纵轴为类目型。
 *
 */
define(function (require) {
    var Base = require('./base');
    
    var LineShape = require('zrenderjs/shape/Line');
    
    var ecConfig = require('../config');
    var ecData = require('../util/ecData');
    var zrUtil = require('zrenderjs/tool/util');
    var zrColor = require('zrenderjs/tool/color');
    
    /**
     * 构造函数
     * @param {Object} messageCenter echart消息中心
     * @param {ZRender} zr zrender实例
     * @param {Object} option 图表选项
     *     @param {string=} option.xAxis.type 坐标轴类型，横轴默认为类目型'category'
     *     @param {string=} option.yAxis.type 坐标轴类型，纵轴默认为类目型'value'
     * @param {Object} component 组件
     * @param {string} axisType 横走or纵轴
     */
    function Axis(ecTheme, messageCenter, zr, option, myChart, axisType) {
        Base.call(this, ecTheme, messageCenter, zr, option, myChart);
        
        this.axisType = axisType;
        this._axisList = [];
        
        this.refresh(option);
    }
    
    Axis.prototype = {
        type: ecConfig.COMPONENT_TYPE_AXIS,
        axisBase: {
            // 轴线
            _buildAxisLine: function () {
                var lineWidth = this.option.axisLine.lineStyle.width;
                var halfLineWidth = lineWidth / 2;
                var axShape = {
                    _axisShape: 'axisLine',
                    zlevel: this.getZlevelBase(),
                    z: this.getZBase() + 3,
                    hoverable: false
                };
                var grid = this.grid;
                switch (this.option.position) {
                    case 'left' :
                        axShape.style = {
                            xStart: grid.getX() - halfLineWidth,
                            yStart: grid.getYend(),
                            xEnd: grid.getX() - halfLineWidth,
                            yEnd: grid.getY(),
                            lineCap: 'round'
                        };
                        break;
                    case 'right' :
                        axShape.style = {
                            xStart: grid.getXend() + halfLineWidth,
                            yStart: grid.getYend(),
                            xEnd: grid.getXend() + halfLineWidth,
                            yEnd: grid.getY(),
                            lineCap: 'round'
                        };
                        break;
                    case 'bottom' :
                        axShape.style = {
                            xStart: grid.getX(),
                            yStart: grid.getYend() + halfLineWidth,
                            xEnd: grid.getXend(),
                            yEnd: grid.getYend() + halfLineWidth,
                            lineCap: 'round'
                        };
                        break;
                    case 'top' :
                        axShape.style = {
                            xStart: grid.getX(),
                            yStart: grid.getY() - halfLineWidth,
                            xEnd: grid.getXend(),
                            yEnd: grid.getY() - halfLineWidth,
                            lineCap: 'round'
                        };
                        break;
                }
                var style = axShape.style;
                if (this.option.name !== '') { // 别帮我代码规范
                    style.text = this.option.name;
                    style.textPosition = this.option.nameLocation;
                    style.textFont = this.getFont(this.option.nameTextStyle);
                    if (this.option.nameTextStyle.align) {
                        style.textAlign = this.option.nameTextStyle.align;
                    }
                    if (this.option.nameTextStyle.baseline) {
                        style.textBaseline = this.option.nameTextStyle.baseline;
                    }
                    if (this.option.nameTextStyle.color) {
                        style.textColor = this.option.nameTextStyle.color;
                    }
                }
                style.strokeColor = this.option.axisLine.lineStyle.color;
                
                style.lineWidth = lineWidth;
                // 亚像素优化
                if (this.isHorizontal()) {
                    // 横向布局，优化y
                    style.yStart 
                        = style.yEnd 
                        = this.subPixelOptimize(style.yEnd, lineWidth);
                }
                else {
                    // 纵向布局，优化x
                    style.xStart 
                        = style.xEnd 
                        = this.subPixelOptimize(style.xEnd, lineWidth);
                }
                
                style.lineType = this.option.axisLine.lineStyle.type;
                
                axShape = new LineShape(axShape);
                this.shapeList.push(axShape);
            },
            
            _axisLabelClickable: function(clickable, axShape) {
                if (clickable) {
                    ecData.pack(
                        axShape, undefined, -1, undefined, -1, axShape.style.text
                    );
                    axShape.hoverable = true;
                    axShape.clickable = true;
                    axShape.highlightStyle = {
                        color: zrColor.lift(axShape.style.color, 1),
                        brushType: 'fill'
                    };
                    return axShape;
                }
                else {
                    return axShape;
                }
            },
            
            refixAxisShape: function(zeroX, zeroY) {
                if (!this.option.axisLine.onZero) {
                    return;
                }
                var tickLength;
                if (this.isHorizontal() && zeroY != null) {
                    // 横向布局调整纵向y
                    for (var i = 0, l = this.shapeList.length; i < l; i++) {
                        if (this.shapeList[i]._axisShape === 'axisLine') {
                            this.shapeList[i].style.yStart 
                                = this.shapeList[i].style.yEnd 
                                = this.subPixelOptimize(
                                    zeroY, this.shapeList[i].stylelineWidth
                                );
                            this.zr.modShape(this.shapeList[i].id);
                        }
                        else if (this.shapeList[i]._axisShape === 'axisTick') {
                            tickLength = this.shapeList[i].style.yEnd 
                                         - this.shapeList[i].style.yStart;
                            this.shapeList[i].style.yStart = zeroY - tickLength;
                            this.shapeList[i].style.yEnd = zeroY;
                            this.zr.modShape(this.shapeList[i].id);
                        }
                    }
                }
                if (!this.isHorizontal() && zeroX != null) {
                    // 纵向布局调整横向x
                    for (var i = 0, l = this.shapeList.length; i < l; i++) {
                        if (this.shapeList[i]._axisShape === 'axisLine') {
                            this.shapeList[i].style.xStart 
                                = this.shapeList[i].style.xEnd 
                                = this.subPixelOptimize(
                                    zeroX, this.shapeList[i].stylelineWidth
                                );
                            this.zr.modShape(this.shapeList[i].id);
                        }
                        else if (this.shapeList[i]._axisShape === 'axisTick') {
                            tickLength = this.shapeList[i].style.xEnd 
                                         - this.shapeList[i].style.xStart;
                            this.shapeList[i].style.xStart = zeroX;
                            this.shapeList[i].style.xEnd = zeroX + tickLength;
                            this.zr.modShape(this.shapeList[i].id);
                        }
                    }
                }
            },
            
            getPosition: function () {
                return this.option.position;
            },
            
            isHorizontal: function() {
                return this.option.position === 'bottom' || this.option.position === 'top';
            }
        },
        /**
         * 参数修正&默认值赋值，重载基类方法
         * @param {Object} opt 参数
         */
        reformOption: function (opt) {
            // 不写或传了个空数值默认为数值轴
            if (!opt || (opt instanceof Array && opt.length === 0)) {
                opt = [ { type: ecConfig.COMPONENT_TYPE_AXIS_VALUE } ];
            }
            else if (!(opt instanceof Array)){
                opt = [opt];
            }

            // 最多两条，其他参数忽略
            if (opt.length > 2) {
                opt = [opt[0], opt[1]];
            }

            if (this.axisType === 'xAxis') {
                // 横轴位置默认配置
                if (!opt[0].position            // 没配置或配置错
                    || (opt[0].position != 'bottom' && opt[0].position != 'top')
                ) {
                    opt[0].position = 'bottom';
                }
                if (opt.length > 1) {
                    opt[1].position = opt[0].position === 'bottom' ? 'top' : 'bottom';
                }

                for (var i = 0, l = opt.length; i < l; i++) {
                    // 坐标轴类型，横轴默认为类目型'category'
                    opt[i].type = opt[i].type || 'category';
                    // 标识轴类型&索引
                    opt[i].xAxisIndex = i;
                    opt[i].yAxisIndex = -1;
                }
            }
            else {
                // 纵轴位置默认配置
                if (!opt[0].position            // 没配置或配置错
                    || (opt[0].position != 'left'  && opt[0].position != 'right')
                ) {
                    opt[0].position = 'left';
                }

                if (opt.length > 1) {
                    opt[1].position = opt[0].position === 'left' ? 'right' : 'left';
                }

                for (var i = 0, l = opt.length; i < l; i++) {
                    // 坐标轴类型，纵轴默认为数值型'value'
                    opt[i].type = opt[i].type || 'value';
                    // 标识轴类型&索引
                    opt[i].xAxisIndex = -1;
                    opt[i].yAxisIndex = i;
                }
            }

            return opt;
        },
        
        /**
         * 刷新
         */
        refresh: function (newOption) {
            var axisOption;
            if (newOption) {
                this.option = newOption;
                if (this.axisType === 'xAxis') {
                    this.option.xAxis = this.reformOption(newOption.xAxis);
                    axisOption = this.option.xAxis;
                }
                else {
                    this.option.yAxis = this.reformOption(newOption.yAxis);
                    axisOption = this.option.yAxis;
                }
                this.series = newOption.series;
            }
    
            var CategoryAxis = require('./categoryAxis');
            var ValueAxis = require('./valueAxis');
            var len = Math.max((axisOption && axisOption.length || 0), this._axisList.length);
            for (var i = 0; i < len; i++) {
                if (this._axisList[i]   // 已有实例
                    && newOption        // 非空刷新
                    && (!axisOption[i] || this._axisList[i].type != axisOption[i].type) // 类型不匹配
                ) {
                    this._axisList[i].dispose && this._axisList[i].dispose();
                    this._axisList[i] = false;
                }
                
                if (this._axisList[i]) {
                    this._axisList[i].refresh && this._axisList[i].refresh(
                        axisOption ? axisOption[i] : false,
                        this.series
                    );
                }
                else if (axisOption && axisOption[i]) {
                    this._axisList[i] =  axisOption[i].type === 'category'
                                         ? new CategoryAxis(
                                               this.ecTheme, this.messageCenter, this.zr,
                                               axisOption[i], this.myChart, this.axisBase
                                           )
                                         : new ValueAxis(
                                               this.ecTheme, this.messageCenter, this.zr,
                                               axisOption[i], this.myChart, this.axisBase,
                                               this.series
                                           );
                    
                }
            }
        },

        /**
         * 根据值换算位置
         * @param {number} idx 坐标轴索引0~1
         */
        getAxis: function (idx) {
            return this._axisList[idx];
        },

        clear: function () {
            for (var i = 0, l = this._axisList.length; i < l; i++) {
                this._axisList[i].dispose && this._axisList[i].dispose();
            }
            this._axisList = [];
        }
    };
    
    zrUtil.inherits(Axis, Base);
    
    require('../component').define('axis', Axis);
     
    return Axis;
});