import Group from '../shapes/group';
import Point from '../geometry/point';
import SurfaceFactory from './surface-factory';
import { Observable } from '../common';
import { eventElement, eventCoordinates, elementStyles, elementSize, elementOffset } from '../util';

var events = [
    "click",
    "mouseenter",
    "mouseleave",
    "mousemove",
    "resize"
];

var Surface = (function (Observable) {
    function Surface(element, options) {
        Observable.call(this);

        this.options = Object.assign({}, options);
        this.element = element;
        this.element._kendoExportVisual = this.exportVisual.bind(this);

        this._click = this._handler("click");
        this._mouseenter = this._handler("mouseenter");
        this._mouseleave = this._handler("mouseleave");
        this._mousemove = this._handler("mousemove");

        this._visual = new Group();

        elementSize(element, this.options);

        this.bind(events, this.options);

        this._enableTracking();
    }

    if ( Observable ) Surface.__proto__ = Observable;
    Surface.prototype = Object.create( Observable && Observable.prototype );
    Surface.prototype.constructor = Surface;

    Surface.prototype.draw = function draw (element) {
        this._visual.children.push(element);
    };

    Surface.prototype.clear = function clear () {
        this._visual.children = [];
    };

    Surface.prototype.destroy = function destroy () {
        this._visual = null;
        this.element._kendoExportVisual = null;
        this.unbind();
    };

    Surface.prototype.eventTarget = function eventTarget (e) {
        var this$1 = this;

        var domNode = eventElement(e);
        var node;

        while (!node && domNode) {
            node = domNode._kendoNode;
            if (domNode === this$1.element) {
                break;
            }

            domNode = domNode.parentElement;
        }

        if (node) {
            return node.srcElement;
        }
    };

    Surface.prototype.exportVisual = function exportVisual () {
        return this._visual;
    };

    Surface.prototype.getSize = function getSize () {
        return elementSize(this.element);
    };

    Surface.prototype.currentSize = function currentSize (size) {
        if (size) {
            this._size = size;
        } else {
            return this._size;
        }
    };

    Surface.prototype.setSize = function setSize (size) {
        elementSize(this.element, size);

        this.currentSize(size);
        this._resize();
    };

    Surface.prototype.resize = function resize (force) {
        var size = this.getSize();
        var currentSize = this.currentSize();

        if (force || (size.width > 0 || size.height > 0) && (!currentSize || size.width !== currentSize.width || size.height !== currentSize.height)) {
            this.currentSize(size);
            this._resize(size, force);
            this.trigger("resize", size);
        }
    };

    Surface.prototype.size = function size (value) {
        if (!value) {
            return this.getSize();
        }

        this.setSize(value);
    };

    Surface.prototype.suspendTracking = function suspendTracking () {
        this._suspendedTracking = true;
    };

    Surface.prototype.resumeTracking = function resumeTracking () {
        this._suspendedTracking = false;
    };

    Surface.prototype._enableTracking = function _enableTracking () {};

    Surface.prototype._resize = function _resize () {};

    Surface.prototype._handler = function _handler (eventName) {
        var this$1 = this;

        return function (e) {
            var node = this$1.eventTarget(e);
            if (node && !this$1._suspendedTracking) {
                this$1.trigger(eventName, {
                    element: node,
                    originalEvent: e,
                    type: eventName
                });
            }
        };
    };

    Surface.prototype._elementOffset = function _elementOffset () {
        var element = this.element;
        var ref = elementStyles(element, [ "paddingLeft", "paddingTop" ]);
        var paddingLeft = ref.paddingLeft;
        var paddingTop = ref.paddingTop;
        var ref$1 = elementOffset(element);
        var left = ref$1.left;
        var top = ref$1.top;

        return {
            left: left + parseInt(paddingLeft, 10),
            top: top + parseInt(paddingTop, 10)
        };
    };

    Surface.prototype._surfacePoint = function _surfacePoint (e) {
        var offset = this._elementOffset();
        var coord = eventCoordinates(e);
        var x = coord.x - offset.left;
        var y = coord.y - offset.top;

        return new Point(x, y);
    };

    return Surface;
}(Observable));

Surface.create = function(element, options) {
    return SurfaceFactory.current.create(element, options);
};

Surface.support = {};

export default Surface;
