(function () {
    window.easyClasses = window.easyClasses || {};
    window.easyClasses.agile = window.easyClasses.agile || {};

    /**
     *
     * @param {Issue} issue
     * @param {ListWidget} listWidget
     * @param {bool} [isAvatar]
     * @constructor
     * @extends EasyWidget
     */
    function IssueItemWidget(issue, listWidget, isAvatar) {
        this.maxDistanceToClick = 30;
        this.timeToContextMenu = 1000;
        this.maxTimeToContextMenu = 4000;
        this.maxDistanceCancelingContextMenu = 50;
        this.issue = issue;
        this.listWidget = listWidget;
        this.maxDistance = 0;
        this.template = window.easyTemplates.ListItem;
        this.showTooltip = !!window.easyTemplates.issueCardWidget;
        this.children = [];
        this.repaintRequested = true;
        this.selected = false;
        this.$overlay = null;
        this.$a = null;
        this.actualY = null;
        this.actualX = null;
        this.shiftKey = false;
        this.doScrollUp = false;
        this.doScrollDown = false;
        this.isPossibleTarget = false;
        this.hover = false;
        this.aTouched = false;
        this.dragDomain = listWidget.model.agileRootModel.dragDomain;
        if (!isAvatar) {
            this.issue.register(this.onChange, this);
            window.easyView.root.addItemToDragCollection(this.dragDomain, this, 2);
        }
        this.isAvatar = isAvatar;
        this.destroyed = false;
    }

    window.easyClasses.EasyWidget.extendByMe(IssueItemWidget);

    IssueItemWidget.prototype._functionality = function () {
        this.$cont = this.$target.find(".agile__card");
        if (this.isAvatar)return;
        this.$a = this.$target.find("a");
        this.setDropHover(this.hover);
        this._select(this.selected);
        var _self = this;
        if (this.showTooltip) {
            if (this.issueCardWidget) {
                this.toolTip.destroy();
            } else {
                this.issueCardWidget = new window.easyClasses.IssueCardWidget(this.issue);
            }
            this.toolTip = new window.easyClasses.EasyTooltip(this.issueCardWidget, this.$target, -80, -20);
            _self._suppressTooltipForAWhile();
        }
        this.$target.off("contextmenu.listItem");
        this.$target.on("contextmenu.listItem", function (e) {
            e.preventDefault();
            _self.actualX = e.pageX - $(window).scrollLeft();
            _self.actualY = e.pageY - $(window).scrollTop();
            _self._contextMenu();
            return false;
        });
        this.$target.off("mousedown.listItem");
        this.$target.on("mousedown.listItem", function (e) {
            _self.shiftKey = e.shiftKey;
            if (e.target.parentElement.tagName === "A") {
                if(e.which === 2){
                    return true;
                }else{
                    _self.aTouched = true;
                }
            }
            e.preventDefault();
            if (e.which === 3) {
                _self.actualX = e.pageX - $(window).scrollLeft();
                _self.actualY = e.pageY - $(window).scrollTop();
                _self._contextMenu();
            } else {
                _self.actualX = e.pageX - $(window).scrollLeft();
                _self.actualY = e.pageY - $(window).scrollTop();
                _self.down(e.pageX, e.pageY);
            }
            return false;
        });
        this.$target.off("touchstart.listItem");
        this.$target.on("touchstart.listItem", function (e) {
            if (e.target.parentElement.tagName === "A") {
                _self.aTouched = true;
            }
            e.preventDefault();
            _self._suppressTooltipForAWhile();
            var touch = e.originalEvent.touches[0];
            if (!touch)return false;
            _self.actualX = touch.pageX - $(window).scrollLeft();
            _self.actualY = touch.pageY - $(window).scrollTop();
            _self.down(touch.pageX, touch.pageY, false);
            return false;
        });
        this.$target.off("touchend.listItem");
        this.$target.on("touchend.listItem", function (e) {
            e.preventDefault();
            _self.up();
            return false;

        });
        this.$target.off("touchmove.listItem");
        this.$target.on("touchmove.listItem", function (e) {
            e.preventDefault();
            var touch = e.originalEvent.touches[0];
            _self._suppressTooltipForAWhile();
            if (!touch) {
                return false;
            }
            _self.move(touch.pageX, touch.pageY);
            return false;
        });

        if (this.issue.error) {
            this.$cont.addClass("agile__card--error");
        }
    };


    IssueItemWidget.prototype._suppressTooltipForAWhile = function () {
        var _self = this;
        if(!this.toolTip)return;
        this.toolTip.suppress = true;
        if (this._suppressTooltipTimout) {
            window.clearTimeout(this._suppressTooltipTimout);
        }
        this._suppressTooltipTimout = window.setTimeout(function () {
            _self.toolTip.suppress = false;
        }, 1000);
    };

    IssueItemWidget.prototype.doScroll = function () {
        if (this.doScrollDown) {
            window.scrollBy(0, 9);
        } else if (this.doScrollUp) {
            window.scrollBy(0, -9);
        } else {
            return;
        }
        window.setTimeout($.proxy(this.doScroll, this), 100);

    };

    IssueItemWidget.prototype.down = function (x, y) {
        // this.startX = x;
        // this.startY = y;
        this.maxDistance = 0;
        this.startX = x - $(window).scrollLeft();
        this.startY = y - $(window).scrollTop();
        this.startTime = Date.now();
        this.actionActive = true;
        var _self = this;
        window.easyView.root.dragStartOnDomain(this.dragDomain, this);

        // create overlay div
        this.$overlay = $("<div>").css({
            position: "fixed",
            top: 0,
            left: 0,
            width: window.innerWidth,
            height: window.innerHeight,
            zIndex: 10000,
            cursor: "move"
        });
        $(document.body).append(this.$overlay);


        this.$overlay.on("mouseup.listItem", function (e) {
            e.preventDefault();
            _self.up();

        });
        this.$overlay.on("mousemove.listItem", function (e) {
            e.preventDefault();
            _self.move(e.pageX, e.pageY);
        });
    };
    IssueItemWidget.prototype.move = function (x, y) {
        if (!this.actionActive)return;
        var $window = $(window);
        var scrollY = $window.scrollTop();
        var scrollX = $window.scrollLeft();

        if ((y - scrollY) < 80) {
            this.doScrollUp = true;
            this.doScroll();
        } else {
            this.doScrollUp = false;
        }

        if ((window.innerHeight - y + scrollY) < 80) {
            this.doScrollDown = true;
            this.doScroll();
        } else {
            this.doScrollDown = false;
        }

        this.actualX = x - scrollX;
        this.actualY = y - scrollY;
        if (this.moveDistance() > 15 && !this.avatar) {
            this.createAvatar();
            this.listWidget.model.agileRootModel.firePossiblePhases(this.issue);
        }
        if (this.avatar) {
            this.moveAvatar();
        }
        this.currentDropTarget = window.easyView.root.getCurrentDragTargetWidget(x, y);
    };
    IssueItemWidget.prototype.up = function () {
        this.doScrollDown = false;
        this.doScrollUp = false;
        if (this.$overlay) {
            this.$overlay.remove();
            if (this.avatar) {
                this.avatar.destroy();
            }
            this.avatar = null;
        }
        window.easyView.root.dragStopOnDomain(this.dragDomain);
        this.listWidget.cancelPossiblePhases();
        this.actionActive = false;

        if (this.destroyed)return;

        if (this.forceContextMenu) {
            this._contextMenu();
            return;
        }

        if (this.moveDistance() < this.maxDistanceToClick) {
            if (Date.now() - this.startTime < this.timeToContextMenu) {
                if (this.aTouched) {
                    window.open(this.$a.attr("href"), '_blank');
                    this.aTouched = false;
                } else {
                    var last = window.easyView.root.lastSelectedIssueItemWidget;
                    if (this.shiftKey && last && last !== this && last.listWidget === this.listWidget) {
                        var startIndex = this.listWidget.children.indexOf(this);
                        var endIndex = this.listWidget.children.indexOf(last);
                        if (startIndex > endIndex) {
                            var shiftIndex = startIndex;
                            startIndex = endIndex;
                            endIndex = shiftIndex;
                        }
                        for (var i = startIndex; i <= endIndex; i++) {
                            this.listWidget.children[i]._select(true);
                        }
                    } else {
                        this._select();
                    }
                }
            } else if (Date.now() - this.startTime < this.maxTimeToContextMenu && this.maxDistance < this.maxDistanceCancelingContextMenu) {
                this._contextMenu();
            }
        } else {
            this._drop();
        }
        this.currentDropTarget = null;
    };

    IssueItemWidget.prototype.setDropHover = function (state) {
        if (this.destroyed)return;
        this.hover = state;
        if (state) {
            this.listWidget.setDropHover(true);
        } else {
            this.listWidget.setDropHover(false);
        }
    };

    IssueItemWidget.prototype.onChange = function () {
        this.repaintRequested = true;
    };
    IssueItemWidget.prototype._select = function (selected) {
        window.easyView.root.mapOfPossibleSelectedIssueItemWidgets = window.easyView.root.mapOfPossibleSelectedIssueItemWidgets || {};
        window.easyView.root.lastSelectedIssueItemWidget = window.easyView.root.lastSelectedIssueItemWidget || {};
        if (typeof selected === "undefined") {
            this.selected = !this.selected;
        } else {
            this.selected = selected;
        }
        if (this.selected) {
            window.easyView.root.mapOfPossibleSelectedIssueItemWidgets[this.issue.id] = this;
            window.easyView.root.lastSelectedIssueItemWidget = this;
            this.$cont.addClass("agile__card--selected");
        } else {
            this.$cont.removeClass("agile__card--selected");
        }
    };
    IssueItemWidget.prototype._contextMenu = function () {
        if (this.destroyed)return;
        var i;
        var _self = this;
        if (this._contextMenuOpened || this.listWidget.model.agileRootModel.contextMenuUrl === null) {
            return;
        }
        this._contextMenuOpened = true;
        this._suppressTooltipForAWhile();

        var selected = window.easyView.root.mapOfPossibleSelectedIssueItemWidgets;
        var selectedList = [];
        for (var key in selected) {
            if (!selected.hasOwnProperty(key) || !selected[key].selected)continue;
            selectedList.push(selected[key].issue.id);
        }
        selectedList.push(this.issue.id);

        $.ajax({
            url: this.listWidget.model.agileRootModel.contextMenuUrl,
            data: {ids: selectedList},
            success: function (data) {
                if (_self.destroyed)return;
                var closeContextMenu = function () {
                    _self._contextMenuOpened = false;
                    $(window).unbind("mousedown.contextMenu");
                    $overlay.remove();
                    $menu.remove();
                };
                _self.closeContextMenu = closeContextMenu;
                $("#context-menu").remove();
                var $menu = $("<div>");
                var $overlay = $("<div>").css({
                    position: "fixed",
                    top: 0,
                    left: 0,
                    width: window.innerWidth,
                    height: window.innerHeight,
                    zIndex: 1
                });
                $menu.attr("id", "context-menu");
                $menu.html(data);
                $menu.find(".context-menu-autocomplete").remove();
                window.setTimeout(function () {
                    var x = _self.actualX + 10;
                    var y = _self.actualY + 10;
                    var height = $menu.outerHeight() + 10;
                    var width = $menu.outerWidth() + 10;

                    if (y + height > window.innerHeight) {
                        y = window.innerHeight - height - 10;
                    }

                    if (x + width > window.innerWidth) {
                        x = window.innerWidth - width - 10;
                    }

                    $menu.css({position: "fixed", zIndex: 1000, top: y, left: x});

                    $(window).bind("mousedown.contextMenu", function (e) {
                        if ($(e.target).closest("#context-menu").length == 0) {
                            window.setTimeout(function () {
                                closeContextMenu();
                            }, 50);
                        }
                    });


                    $menu.find("a").each(function (k, v) {
                        var $a = $(v);
                        if (v.href.indexOf("bulk_update") !== -1) {
                            $a.mousedown(function (e) {
                                e.preventDefault();
                                e.stopPropagation();
                                return false;
                            }).mouseup(function (e) {
                                e.preventDefault();
                                e.stopPropagation();
                                return false;
                            }).click(function (e) {
                                e.preventDefault();
                                e.stopPropagation();
                                _self.listWidget.model.agileRootModel.sendBulkUpdate(v.href, function () {
                                    $(window).unbind("mousedown.contextMenu");
                                    closeContextMenu();
                                });
                                return false;
                            });

                        }
                    });
                }, 30);
                $(document.body).append($menu);
                // create overlay div

                $overlay.mousedown(function () {
                    closeContextMenu();
                });

                $overlay.on("touchstart", function () {
                    closeContextMenu();
                });
                $(document.body).append($overlay);
                window.initEasyAutocomplete();
            }
        });
    };
    IssueItemWidget.prototype._drop = function () {
        if (this.destroyed)return;
        if (!this.currentDropTarget)return;
        var targetIssues;

        var selected = window.easyView.root.mapOfPossibleSelectedIssueItemWidgets;
        this.selected = true;
        selected[this.issue.id] = this;

        var toProcess = {};

        this.isPossibleTarget = false;
        for (var key in selected) {
            if (!selected.hasOwnProperty(key))continue;
            var sourceWidget = selected[key];
            if (!sourceWidget.selected)continue;

            var issue = sourceWidget.issue;
            var originalPosition = issue.agile_column_position;
            var sourceIssues = issue.issues;
            var newColumnPosition = null;

            var issueColModel;
            if (this.currentDropTarget.issue !== undefined) {
                issueColModel = this.currentDropTarget.listWidget.model;
            } else {
                issueColModel = this.currentDropTarget.model;
            }
            var phase = issueColModel.column.entityValue;

            if (!issueColModel.issueCanBePlacedHere(issue)) {
                continue;
            }

            this.isPossibleTarget = true;
            if (this.currentDropTarget.issue !== undefined) {
                // drop target is ListWidget
                var targetIssue = this.currentDropTarget.issue;
                targetIssues = targetIssue.issues;
                var isPrev = targetIssues.moveIssueOntoThisIssue(issue, targetIssue);
                issue.next_item_id = isPrev ? null : targetIssue.id;
                issue.prev_item_id = isPrev ? targetIssue.id : null;
                issue["agile_column_filter_value"] = phase;
            } else {
                // drop target is ListItemWidget
                targetIssues = this.currentDropTarget.model.issues;
                var prevIssue;
                issue.prev_item_id = null;
                if (targetIssues.temporarySortedList.length !== 0) {
                    prevIssue = targetIssues.temporarySortedList[targetIssues.temporarySortedList.length - 1];
                    issue.prev_item_id = prevIssue.id;
                    newColumnPosition = prevIssue.agile_column_position + 1;
                }
                issue.next_item_id = null;
            }
            issue["agile_column_filter_value"] = phase;

            (function (issue, sourceIssues, lastPosition) {
                issue.undo = function () {
                    issue.agile_column_position = lastPosition;
                    issue.issues.remove(issue);
                    sourceIssues.add(issue);
                };
            })(issue, sourceIssues, originalPosition);

            if (newColumnPosition) {
                issue.agile_column_position = newColumnPosition;
            }

            toProcess[key] = {
                sourceIssues: sourceIssues,
                targetIssues: targetIssues,
                issue: issue
            };
        }
        for (key in toProcess) {
            if (!selected.hasOwnProperty(key))continue;
            selected[key]._select(false);
            targetIssues = toProcess[key].targetIssues;
            sourceIssues = toProcess[key].sourceIssues;
            issue = toProcess[key].issue;

            if (targetIssues === sourceIssues) {
                $.proxy(this.listWidget.model.sendPositionChange(issue), this.listWidget.model);
                this.listWidget.requestRepaint();
            } else {
                sourceIssues.remove(issue);
                targetIssues.add(issue);
            }
        }
        window.easyView.sticky.scheduleRebuild();

    };

    IssueItemWidget.prototype.moveDistance = function () {
        if (this.actualX == null) {
            return 0;
        }
        var distance = Math.sqrt(Math.pow(this.actualX - this.startX, 2) + Math.pow(this.actualY - this.startY, 2));
        if (distance > this.maxDistance) {
            this.maxDistance = distance;
        }
        return distance;
    };

    IssueItemWidget.prototype.destroy = function () {
        window.easyView.root.removeItemFromDragCollection(this.dragDomain, this);
        this.issue.unRegister(this);
        window.easyClasses.EasyWidget.prototype.destroy.apply(this);
        delete window.easyView.root.mapOfPossibleSelectedIssueItemWidgets[this.issue.id];
        this.issue = null;
        this.listWidget = null;
        this.destroyed = true;
        if (this.$overlay) {
            this.$overlay.remove();
            this.$overlay = null;
        }
        if (this.avatar) {
            this.avatar.destroy();
            this.avatar = null;
        }
        this.$a = null;
        if (this.toolTip) {
            this.toolTip.destroy();
            this.toolTip = null;
        }
        if (this.closeContextMenu) {
            this.closeContextMenu();
            this.closeContextMenu = null;
        }

        if (this._suppressTooltipTimout) {
            window.clearTimeout(this._suppressTooltipTimout);
        }
        this.toolTip = null;
    };


    IssueItemWidget.prototype.createAvatar = function () {
        if (this.destroyed)return;
        this.avatar = new IssueItemWidget(this.issue, this.listWidget, true);
        this.avatar.$target = this.$overlay;
        this.avatar.repaint();
        this.avatar.$cont.addClass("agile__card-avatar");
        var background = this.$cont.css("backgroundColor");
        if (background === "rgba(0, 0, 0, 0)" || background === "transparent") {
            background = "rgba(255, 255, 255, 0.5)";
        }
        this.avatar.$cont.css({
            position: "absolute",
            top: this.actualY,
            left: this.actualX,
            zIndex: -1,
            height: this.$target.height(),
            width: this.$cont.width(),
            backgroundColor: background
        });
    };
    IssueItemWidget.prototype.moveAvatar = function () {
        this.avatar.$cont.css({position: "absolute", top: this.actualY, left: this.actualX});
    };


    /**
     *
     * @override
     */
    IssueItemWidget.prototype.out = function () {
        return this.issue;
    };

    window.easyClasses.agile.IssueItemWidget = IssueItemWidget;

})();
