/*
 * PS 钢笔工具 控制逻辑
 */
define( function ( require, exports, module ) {

    // 资源引入
    var Bezier = require( "graphic/bezier" ),
        Color = require( "graphic/color" ),
        Pen = require( "graphic/pen" ),
        Utils = require( "core/utils" ),
        Vector = require( "graphic/vector" ),
        // 引入可绘制的点集合
        PointGroup = require( "../ps-pen/demo.pointgroup" ),
        BezierPoint = require( "graphic/bezierpoint" );


    function Controller ( paper ) {

        this.paper = paper || null;
        this.bezier = null;
        this.bezierPoints = null;
        this.pointGroup = null;

        this.drawState = false;

        // 记录当前是否处于更新状态
        this.modifyState = false;

        // 记录更新状态的持久信息
        this._modifyStatus = null;

        // 允许重新拖动编辑的
        this.editable = false;

    }

    Utils.extend( Controller.prototype, {

        takeover: function ( paper ) {

            paper && ( this.paper = paper );

            initListener( this );

        },

        enableDraw: function () {
            this.drawState = true;
        },

        disableDraw: function () {
            this.drawState = false;
        },

        enableModify: function () {
            this.modifyState = true;
        },

        disableModify: function () {
            this.modifyState = false;
        },

        // 设置更新状态
        setModifyStatus: function ( status ) {
            this._modifyStatus = status;
        },

        clearModifySatus: function () {
            this._modifyStatus = null;
        },

        getModifyStatus: function () {
            return this._modifyStatus;
        },

        enableEdit: function () {
            this.editable = true;
        },

        disableEdit: function () {
            this.editable = false;
        },

        setBezier: function ( bezier ) {

            this.bezier = bezier;
            this.bezierPoints = [];

            return this;

        },

        getBezier: function () {

            return this.bezier;

        },

        setPointGroup: function ( pointGroup ) {

            this.pointGroup = pointGroup;

            return this;

        },

        getPointGroup: function () {

            return this.pointGroup;

        },

        addPoint: function ( point ) {

            this.bezierPoints && this.bezierPoints.push( point );

            return this;

        },

        getPoints: function () {

            return this.bezierPoints;

        }

    } );


    return Controller;

    // 私有方法实现

    // 初始化交互事件监听器
    function initListener ( controller ) {

            // 记录是否允许所有事件的监听
        var isBegin = false,
            // 记录是否需要更新曲线
            isUpdateable = false,
            paper = controller.paper,
            currentBezier = null,
            currentPointGroup = null;

        paper.on( "mousedown", function ( e ) {

            var point = null;

            e.preventDefault();

            if ( !controller.drawState ) {
                return;
            }

            // 切换监听状态
            if ( !isBegin ) {
                isBegin = true;
                currentBezier = createBezier( paper );
                currentPointGroup = createPointGroup( paper );

                listenPointGroup( currentPointGroup, controller );

                //设置当前controller处理的贝塞尔曲线
                controller.setBezier( currentBezier );
                controller.setPointGroup( currentPointGroup );
            }

            isUpdateable = false;

            // 获取当前鼠标点击在用户坐标系上的映射点
            point = e.getPosition();

            updateBezier( controller, point );

        } );

        // 绘制时 更新控制点
        paper.on( "mousemove", function ( e ) {

            var point = null,
                bezierPoint = null;

            e.preventDefault();

            if ( !controller.drawState ) {
                return;
            }

            if ( !isBegin || isUpdateable ) {
                return;
            }

            point = e.getPosition();

            currentBezier.getLastPoint().setForward( point.x, point.y );
            currentPointGroup.getLastPoint().setForward( point.x, point.y );

        } );

        // 编辑时拖动更新
        paper.on( "mousemove", function ( e ) {

            var mousePoint = null,
                currentPoint = null,
                pointIndex = -1;

            e.preventDefault();

            // 不可编辑
            if ( !controller.editable ) {
                return;
            }

            mousePoint = e.getPosition();
            pointIndex = controller._modifyStatus.pointIndex;
            currentPoint = currentPointGroup.getPointByIndex( pointIndex );

            switch ( controller._modifyStatus.pointType ) {

                case PointGroup.TYPE_FORWARD:
                    currentPoint.setForward( mousePoint.x, mousePoint.y );
                    currentBezier.getPoint( pointIndex ).setForward( mousePoint.x, mousePoint.y );
                    break;

                case PointGroup.TYPE_BACKWARD:
                    currentPoint.setBackward( mousePoint.x, mousePoint.y );
                    currentBezier.getPoint( pointIndex ).setBackward( mousePoint.x, mousePoint.y );
                    break;

                case PointGroup.TYPE_VERTEX:
                    currentPoint.moveTo( mousePoint.x, mousePoint.y );
                    currentBezier.getPoint( pointIndex ).moveTo( mousePoint.x, mousePoint.y );
                    break;

            }


        } );

        paper.on( "mouseup", function () {

            if ( controller.drawState ) {

                isUpdateable = isBegin;

            } else if ( controller.modifyState ) {

                controller.disableEdit();
                // 清空状态
                controller.clearModifySatus();

            }

        } );

    }

    // 画贝塞尔曲线
    function updateBezier ( controller, point ) {

        var bezierPoint = new BezierPoint( point.x, point.y, true );

        //添加可绘制控制点
        controller.getPointGroup().addPoint( bezierPoint.clone() );

        //记录贝塞尔的控制点
        controller.addPoint( bezierPoint );

        //更新贝塞尔曲线的点
        controller.getBezier().setPoints( controller.getPoints() );


    }

    // 创建一个新的贝塞尔
    function createBezier ( paper ) {

        var bezier = new Bezier();

        bezier.stroke( new Pen( new Color( "black" ) ).setWidth( 100 ) );
        paper.addShape( bezier );

        return bezier;

    }

    function createPointGroup ( paper ) {

        var pointGroup = new PointGroup();

        paper.addShape( pointGroup );

        return pointGroup;

    }

    // 监听点上的事件
    function listenPointGroup ( pointGroup, controller ) {

        pointGroup.on( "pointmousedown", function ( e ) {

            var currentPoint = null,
                currentType = null,
                index = -1,
                vertexWidth = 0;

            // 非modify状态, 不处理
            if ( !controller.modifyState ) {
                return;
            }

            index = e.targetPointIndex;
            currentType = e.targetPointType;
            currentPoint = pointGroup.getPointByIndex( index );

            // 获取到当前顶点的宽度
            vertexWidth = pointGroup.getVertexWidth();

            // 检查当前点击的点的控制点是否和顶点重叠
            // 如果重叠了, 则认为点击是发生在forward的控制点上的
            if ( currentType === PointGroup.TYPE_VERTEX ) {

                //更新点类型
                switch ( checkOverlapping( currentPoint, vertexWidth ) ) {

                    case 1:
                        currentType = PointGroup.TYPE_FORWARD;
                        break;

                    case 2:
                        currentType = PointGroup.TYPE_BACKWARD
                        break;

                }

            }


            // 运行更新
            controller.enableEdit();

            controller.setModifyStatus( {
                pointType: currentType,
                pointIndex: index
            } );

            //更新当前的点
            this.selectPoint( index );

        } );

    }

    // 工具方法, 检测贝塞尔曲线上的点的控制点和顶点是否重叠在一起
    // 参数distance控制了点之间的最小距离, 如果不大于该距离, 则认为是重叠的
    // 返回值有: 0: 无重叠, 1: forward重叠, 2: backward重叠
    function checkOverlapping ( bezierPoint, distance ) {

        var forward = bezierPoint.getForward(),
            backward = bezierPoint.getBackward(),
            vertex = bezierPoint.getVertex();

        if ( Vector.fromPoints( forward, vertex ).length() <= distance ) {

            // forward重叠
            return 1;

        } else if ( Vector.fromPoints( backward, vertex ).length() <= distance ) {

            // backward重叠
            return 2;

        }

        // 无重叠
        return 0;

    }


} );