'use strict';

import svgns from './svgns';

class Canvas {

    constructor( container ) {
        if ( typeof container === 'string' ) {
            this._container = document.getElementById( container );
            this.init();
        } else {
            this._container = container;
            this.init();
        }
    }

    svg() {
        return this._svg;
    }

    group() {
        return this._g;
    }

    transformedPoint( x, y ) {
        return {
            x: -( this._translate.x - x ) / this._scale,
            y: -( this._translate.y - y ) / this._scale
        };
    }

    draw() {
        const transform = {
            translate: {
                x: {
                    min: this.transformedPoint( 0, 0 ).x,
                    max: this.transformedPoint( this._width, 0 ).x,
                },
                y: {
                    min: this.transformedPoint( 0, this._height * 2 ).y,
                    max: this.transformedPoint( 0, -this._height ).y,
                }
            },
            width: this._width,
            height: this._height,
            scale: this._scale
        };
        for ( let type in this._elements ) {
            let group = this._elements[ type ];
            for ( let i in group ) {
                group[ i ].draw( this._g, transform );
            }
        }
    }

    init() {

        this._svg = document.createElementNS( svgns, 'svg' );
        this._g = document.createElementNS( svgns, 'g' );

        this._svg.appendChild( this._g );
        this._container.appendChild( this._svg );

        this._width = this._container.offsetWidth;
        this._height = this._container.offsetHeight;

        this._svg.setAttribute( 'style', `width: ${ this._width }px; height: ${ this._height }px;` );
        // this._g.style.transition = 'transform 250ms ease-in-out';

        this._elements = {};

        this._translate = {
            x: this._width * .5,
            y: this._height * .5,
        };

        this._scaleFactor = 1.10;
        this._steps = 0;
        this._scale = 1;

        this._time = Date.now();
        this.draw( false );
        this._delay = ( Date.now() - this._time ) * 2;

        this._lastX = this._width / 2;
        this._lastY = this._height / 2;

        this._dragStart;
        this._dragged;

        this._lastUpdate = true;
        this.position();
        this.dragable();
        this.zoomable();

        delete this.init;
    }

    position() {
        this._g.setAttribute( 'transform', `translate(${ this._translate.x },${ this._translate.y })scale(${ this._scale })` );
    }

    zoomable() {
        const that = this;

        function handleScroll( e ) {
            e.preventDefault();
            const delta = e.wheelDelta ? e.wheelDelta / 40 : e.detail ? -e.detail : 0;
            that.zoom( delta, e );
            return e.preventDefault() && false;
        }

        this._svg.addEventListener( 'DOMMouseScroll', handleScroll );
        this._svg.addEventListener( 'mousewheel', handleScroll );
    }

    zoom( clicks ) {

        let pt = this.transformedPoint( this._lastX, this._lastY );
        const factor = Math.pow( this._scaleFactor, clicks );

        this._translate.x += pt.x  * this._scale;
        this._translate.y += pt.y  * this._scale;

        this._steps += clicks / 3;
        this._scale = Math.abs( Math.pow( factor > 1 ? factor : 1 / factor, this._steps ) );

        this.position();

        this._translate.x -= pt.x * this._scale;
        this._translate.y -= pt.y * this._scale;

        this.position();

        this.draw();
    }

    dragable() {
        this._container.addEventListener( 'mousedown', ( e ) => {
            document.body.style.mozUserSelect = document.body.style.webkitUserSelect = document.body.style.userSelect = 'none';

            this._dragStart = { x: e.pageX, y: e.pageY };
            this._drag = true;

        }, false );

        document.addEventListener( 'mousemove', ( e ) => {

            this._lastX = e.pageX - this._container.offsetLeft;
            this._lastY = e.pageY - this._container.offsetTop;

            if ( this._drag ) {
                const vector = {
                    x: ( e.pageX - this._dragStart.x )/* / this._scale */,
                    y: ( e.pageY - this._dragStart.y )/* / this._scale */,
                };

                this._translate.x += vector.x;
                this._translate.y += vector.y;

                this._dragStart.x = e.pageX;
                this._dragStart.y = e.pageY;

                this.position();
                // this.draw();
            }

        }, false );

        document.addEventListener( 'mouseup', () => {
            if ( this._drag ) {
                this.draw();
                this._drag = false;
            }
        }, false );
    }
}

export default Canvas;
