﻿function WebPartBox() {
    this.s = { w: 0, h: 0 }; this.p = { x: 0, y: 0 };
    this.Read = function(o, r) { if (!o) return; if (!r) r = false; if (r) { this.s = GetObjectSize(o); this.p = GetObjectPosition(o); o.setAttribute("wp-x", this.p.x); o.setAttribute("wp-y", this.p.y); o.setAttribute("wp-w", this.s.w); o.setAttribute("wp-h", this.s.h); return; }; var lx = o.getAttribute("wp-x"); var ly = o.getAttribute("wp-y"); var lw = o.getAttribute("wp-w"); var lh = o.getAttribute("wp-h"); if (!lx || !ly || !lw || !lh) { this.Read(o, true); return; }; this.p.x = parseInt(lx); this.p.y = parseInt(ly); this.s.w = parseInt(lw); this.s.h = parseInt(lh); }
    this.Area = function() { return this.s.w * this.s.h; }
    this.Clone = function() { var l = new WebPartBox(); l.s.w = this.s.w; l.s.h = this.s.h; l.p.x = this.p.x; l.p.y = this.p.y; return l; }
    this.IsBigger = function(o) { return (this.Area() > o.Area()); }
    this.Union = function(o) { var lx = this.AreaX(o); var ly = this.AreaY(o); var lp = new WebPartBox(); lp.s.w = lx[1]; lp.s.h = ly[1]; lp.p.x = lx[0]; lp.p.y = ly[0]; return lp; }
    this._lineC = function(p1, p2) { var lp1 = p1; var lp2 = p2; if (p1[0] > p2[0]) { lp1 = p2; lp2 = p1; }; if ((lp1[0] + lp1[1]) < lp2[0]) return [0, 0]; var lo = [0, 0]; var ll1 = lp1[0] + lp1[1]; var ll2 = lp2[0] + lp2[1]; lo[0] = lp2[0]; lo[1] = lp1[0] + lp1[1] - lp2[0]; return lo; }
    this.AreaX = function(o) { return this._lineC([this.p.x, this.s.w], [o.p.x, o.s.w]); }
    this.AreaY = function(o) { return this._lineC([this.p.y, this.s.h], [o.p.y, o.s.h]) }
    this.ApplyToElement = function(o) { o.style.left = this.p.x + "px"; o.style.top = this.p.y + "px"; o.style.width = this.s.w + "px"; o.style.height = this.s.h + "px"; }
    this.UnionPercentage = function(o) { var lAll = this.Area(); var lUnion = o.Area(); if (lAll == 0) return 0; return Math.round(100 * (lUnion / lAll)); }
}

function ZebraDragWebPartClass(p) {
    this.p = p; this.c = null; this._box = null; this.box = null; this.cs = null; this._dp = null; this.currentZone = null; this.startZone = null; this.currentPart = null; this._lock = false; this._dc = false; this._initialized = false;
    if (!p.z.m.empty(p.z.m.drag)) { p.z.m.drag.stopDrag(); p.z.m.drag = null; }
    this.clear = (function() {
        if (this.c && this.c.parentNode) this.c.parentNode.removeChild(this.c);
        if (this.cs && this.cs.parentNode) this.cs.parentNode.removeChild(this.cs);
        this.p.o.style.display = ""; this.c = null; this.box = null; this._box = null; this.cs = null; this._dp = null; this.startZone = null; this.p.z.m.reinit(); this.currentZone = null; this.currentPart = null;
        this.currentIsUp = false; this._lock = false; this.p.z.m.drag = null; this._oe = null; this._initialized = false;
    }).bind(this);

    this.startDrag = (function(e) {
        AddEvent(document, "mouseup", this.stopDrag);
        AddEvent(document, "mousemove", this.dragging);
        document.onmousemove = function() { return false; }

        DisableSelection(document.body);
        this.clear();
        this.currentZone = this.p.z;
        this.startZone = this.p.z;
        this.currentPart = this.p;
        this.c = document.createElement("div");
        this.box = new WebPartBox();
        this.box.Read(this.p.o);
        this.box.off = GetMouseOffset(this.p.o, e);
        this._box = this.box;

        this.cs = document.createElement("div");
        this.cs.className = "wppc";
        this.cs.id = "carret";

        this.c.className = "trans wppc";
        this.c.innerHTML = this.p.o.innerHTML;
        this.c.style.position = "absolute";

        this.dragging(e);

        this.c.style.width = this.box.s.w + "px";
        this.c.style.height = this.box.s.h + "px";
        this.cs.style.width = this.c.style.width;
        this.cs.style.height = this.c.style.height;

        this._moveCarret(this.p, this.p, true);
        this._oe = this.p.o.parentNode.removeChild(this.p.o);
        document.body.appendChild(this.c);
        this._initialized = true;
    }).bind(this);

    this.stopDrag = (function(e) {
        if (!this._initialized) return;
       // RemoveEvent(document, "mouseup", this.stopDrag);
       // RemoveEvent(document, "mousemove", this.dragging);
      
            this.currentZone.o.replaceChild(this._oe, this.cs);
       
        EnableSelection(document.body);

        if (this.currentZone.id != this.startZone.id) {
            var inx = this.startZone.findWebPart(this.p);
            this.p.z = this.currentZone;
            this.startZone.webParts.splice(inx, 1);
            this.currentZone.webParts[this.currentZone.webParts.length] = this.p;
        }

        try {
            if ((this.p.ref != this.currentPart.ref || this.startZone.ref != this.currentZone.ref)) {
                zwpm.swp({
                    startZone: this.startZone.ref,
                    currentZone: this.currentZone.ref,
                    part: this.p.ref,
                    partCurrent: this.currentPart.ref,
                    isUp: this.currentIsUp
                });
            }
        }
        finally {
            this.clear();
        }

    }).bind(this);

    this._moveCarret = function(part, isUp) {

        var lcs = (this.cs.parentNode) ? this.cs.parentNode.removeChild(this.cs) : this.cs;
        var lco = (part && part.o) ? part.o : null;
        this.currentIsUp = isUp;
        if (isUp) {
            this.currentZone.o.insertBefore(lcs, lco);
        } else {
            this.currentZone.o.insertBefore(lcs, this.findNext(lco));
        }
        this.currentZone.reinit();
    }

    this.findNext = function(o) { if (!o) return null; var e = o.nextSibling; while (e && e.nodeType != 1) { e = e.nextSibling; } return e; }

    this.OnZoneChange = function(newZone, oldZone) {
        var lTopPart = null;
        var lBottomPart = null;
        var lOut = false;

        this.currentZone = newZone;
        for (var i = 0; i < newZone.webParts.length; i++) {
            if (this.p == newZone.webParts[i]) continue;
            if (!newZone.webParts[i].canDrag) continue;
            if (!lTopPart) {
                lTopPart = newZone.webParts[i];
            } else {
                if (lTopPart.box.p.y > newZone.webParts[i].box.p.y) { lTopPart = newZone.webParts[i]; };
            }

            if (!lBottomPart) {
                lBottomPart = newZone.webParts[i];
            } else {
                if (lBottomPart.box.p.y < newZone.webParts[i].box.p.y) lBottomPart = newZone.webParts[i];
            }
        }

        if (!lTopPart || !lBottomPart) {
            this._moveCarret(null, true);
            lOut = true;
        }
        else {
            if (this.box.p.y > lBottomPart.box.p.y) {
                this._moveCarret(lBottomPart, false);
                lOut = true;
            }
            if (this.box.p.y < lTopPart.box.p.y) {
                this._moveCarret(lTopPart, true);
                lOut = true;
            }
        }


        newZone.reinit();
        oldZone.reinit();
        return lOut;
    }

    this.OnPartChange = function(part, isUp) { this._moveCarret(part, isUp); this.currentPart = part; }

    this.doDrag = function(e) {
        if (this._lock) return;
        var mc = GetMouseCoords(e);
        if (!this.box || !mc) return;
        if (!this._box) this._box = this.box.Clone();

        this.box.p.x = mc.x - this.box.off.x;
        this.box.p.y = mc.y - this.box.off.y;
        this.c.style.left = this.box.p.x + "px";
        this.c.style.top = this.box.p.y + "px";

        var lIsPartProcessed = false;

        // evaluate zones
        for (var i = 0; i < zwpm.zones.length; i++) {
            var lz = zwpm.zones[i];
            if (lz == this.currentZone) continue;

            var lNewOverlap = this.box.AreaX(lz.box)[1];
            var lOldOverlap = this._box.AreaX(lz.box)[1];
            if (lNewOverlap > lOldOverlap) {
                var lop = (100 * lNewOverlap) / lz.box.s.w;
                if (lop > 30) {
                    try {
                        this._lock = true;
                        lIsPartProcessed = this.OnZoneChange(lz, this.currentZone);
                    } finally {
                        this._lock = false;
                        break;

                    }
                }
            }
        }

        if (!lIsPartProcessed) {
            // evaluate parts
            for (var i = 0; i < this.currentZone.webParts.length; i++) {
                var lp = this.currentZone.webParts[i];
                if (!lp.canDrag) continue;
                //if (lp.id == this.currentPart.id) continue;

                var lNewOverlapBox = this.box.Union(lp.box);
                var lOldOverlapBox = this._box.Union(lp.box);

                if (lNewOverlapBox.IsBigger(lOldOverlapBox)) {
                    var lop = lp.box.UnionPercentage(lNewOverlapBox);

                    if (lop > 20) {
                        try {
                            this._lock = true;
                            this.OnPartChange(lp, this.box.p.y < this._box.p.y);
                        } finally {
                            this._lock = false;
                            break;

                        }
                    }
                }
            }
        }

        this._box = this.box.Clone();
    }

    this.dragging = (function(e) { this.doDrag(e); e.cancelBubble = true; e.returnValue = false; }).bind(this);
}

function ZebraWebPartTitleClass(p, o) {
    this.o = o; this.id = o.id; this.p = p;
    this.__wpmd = (function(e) { this.p.z.m.drag = new ZebraDragWebPartClass(this.p); this.p.z.m.drag.startDrag(e); }).bind(this);
    this.initialize = (function() { if (this.p.canDrag && this.id && this.id.length > 0) { this.o = document.getElementById(this.id); if (!o) return; AddEvent(this.o, "mousedown", this.__wpmd); } }).bind(this);
    this._ajaxFix = (function() { if (this.p.canDrag) { this.o = document.getElementById(this.id); AddEvent(this.o, "mousedown", this.__wpmd); } }).bind(this);
    this.dispose = (function() { if (this.o) RemoveEvent(this.o, "mousedown", this.__wpmd); this.o = null; }).bind(this);
}

function ZebraWebPartClass(o) {
    this.z = o.z; this.o = o.o; this.id = null; this.index = o.i; this.tid = null; this.ref = null;
    this.title = null;
    this.box = null;
    this.canDrag = null;

    this.initialize = function() {
  
        this.id = this.o.id;
        this.canDrag = this.o.getAttribute("wp-cd");
        this.ref = this.o.getAttribute("wp-cref");

        this.box = new WebPartBox();
        this.box.Read(this.o);

        var le = getElementsByClassName("wpTitle", "*", this.o);
        for (var i = 0; i < le.length; i++) {
            this.title = new ZebraWebPartTitleClass(this, le[i]);
            this.title.initialize();
        }

    }

    this.reinit = function() {
        if (!this.box) this.box = new WebPartBox();
        this.box.Read(this.o, true);
    }

    this._ajaxFix = function() {
        this.box.Read(this.o, true);
        if (!this.z.m.empty(this.title)) this.title._ajaxFix();
    }

    this.dispose = function() {
        this.o = null;
        this.box = null;
        if (!this.z.m.empty(this.title)) this.title.dispose();
    }
}
function ZebraWebZoneClass(o) {
    this.partAlreadyAdded = function(partId) { var m = 'WebPart has already been added: ' + partId; var e = new Error(m); e.name = 'partAlreadyAdded'; return e; }
    this.m = zwpm;
    this.o = o; this.id = null; this.ref = null; this.webParts = new Array(); this.box = null;

    this.initialize = function() {
        this.ref = this.o.getAttribute("wp-cref");
        this.id = this.o.id;
        this.box = new WebPartBox();
        this.box.Read(this.o);
        // alert(this.box);

        var le = getElementsByClassName("wpPart", "*", this.o);
        
        for (var i = 0; i < le.length; i++) {
            var o = le[i];
            var lc = { 'i': i, 'z': this, 'o': o };
            var lPart = new ZebraWebPartClass(lc);
            this.webParts[this.webParts.length] = lPart;
            lPart.initialize();
        }
    }

    this.reinit = function() {
        if (!this.box) this.box = new WebPartBox();
        this.box.Read(this.o, true);
        for (var i = 0; i < this.webParts.length; i++) {
            this.webParts[i].reinit();
        }
    }

    this._ajaxFix = function() {
        for (var i = 0; i < this.webParts.length; i++) {
            this.webParts[i]._ajaxFix();
        }
    }

    this.findWebPart = function(p) {
        for (var i = 0; i < this.webParts.length; i++) {
            if (this.webParts[i].id == p.id) return i;

        }
        return null;
    }

    this.findWebPartByRef = function(ref) {
        for (var i = 0; i < this.webParts.length; i++) {
            if (this.webParts[i].ref == ref) return i;

        }
        return null;
    }

    this.dispose = function() {
        this.o = null;
        this.box = null;
        for (var i = 0; i < this.webParts.length; i++) {
            this.webParts[i].dispose();
        }
    }

    this.addWebParts = function(webParts) {
        if (this.m.empty(webParts)) return;
        for (var i = 0; i < webParts.length; i++) {
            var lwp = webParts[i];

            if (this.isWebPartAdded(lwp.wpid)) throw this.partAlreadyAdded(lwp.wpid);

            var op = new ZebraWebPartClass(this, i, lwp);
            this.webParts[this.webParts.length] = op;

        }
    }

    this.isWebPartAdded = function(id) {
        return this.m.isAdded(this.webParts, id);
    }
}

function ZebraWebPartManagerClass() {
    this.zoneAlreadyAdded = function(zoneId) { var m = 'Zone has already been added: ' + zoneId; var e = new Error(m); e.name = 'zoneAlreadyAdded'; return e; }
    this.zoneNotExists = function(zoneId) { var m = 'Zone does not exist: ' + zoneId; var e = new Error(m); e.name = 'zoneNotExists'; return e; }
    this.zones = new Array();
    this.space = null; 
    this.tab = null;

    this.z = function(id) {
        for (var i = 0; i < zwpm.zones.length; i++) {
            if (zwpm.zones[i].id == id) return zwpm.zones[i];
        }
        throw this.zoneNotExists(id);
    }

    this.isZoneAdded = function(id) {
        return this.isAdded(this.zones, id);
    }

    this.initialize = function() {
        this.dispose();
        var le = getElementsByClassName("wpZone", "*", null);
        
        for (var i = 0; i < le.length; i++) {
            var lZone = new ZebraWebZoneClass(le[i]);
            this.zones[this.zones.length] = lZone;
            lZone.initialize();
        }

        //        tst = document.createElement("div");
        //        tst.style.border = "2px solid green";
        //        tst.style.position = "absolute";
        //        document.body.appendChild(tst);

    }

    this.reinit = function() {
        for (var i = 0; i < zwpm.zones.length; i++) {
            zwpm.zones[i].reinit();
        }

    }

    this._ajaxFix = function(partRef) {
       if (partRef == undefined || !partRef) {
           
               this.initialize();
            
            return;
        };
        for (var i = 0; i < zwpm.zones.length; i++) {
            var lp = zwpm.zones[i].findWebPartByRef(partRef);
            if (lp) zwpm.zones[i].webParts[lp].initialize();
        };
    }

    this.dispose = function() {
        for (var i = 0; i < zwpm.zones.length; i++) {
            zwpm.zones[i].dispose();
        }
    }

    this.empty = function(o) {
        if (!o) return true;
        if (o == '') return true;
        if (o == "undefined") return true;

        return false;
    }

    this.isAdded = function(coll, id) {
        for (var i = 0; i < coll.length; i++) {
            if (coll[i].id == id) return true;
        }
        return false;
    }

    this._cwp = null;
    this.drag = null;

    this.cc = function(a) {

    };

    this.dwpFinish = (function(pid) {
         if (!pid || pid == undefined) return;
        for (var i = 0; i < this.zones.length; i++) {
            var lz = this.zones[i];

            var inx = lz.findWebPartByRef(pid);
            if (inx == null) continue;
            var lo = lz.webParts[inx].o;
            if (lo) lo.parentNode.removeChild(lo);
            lz.webParts.splice(inx, 1);


        }
    }).bind(this);

    this.callServerOptions = {};

    this.callServer = (function(method, args, options) {
        if (!options || options == undefined) options = {};
        if (!args || args == undefined) args = [];
        jQuery.extend(options, this.callServerOptions);
        options.methodName = method;
        options.args = args;
        options.postType = "POST";
        options.async = true;

        zajaxm.call(options);
    }).bind(this);

    this.dwp = function(wpid) {
        this.callServer("DeleteWebPart", [this.space, this.tab, wpid, null]);
        this.dwpFinish(wpid);
    };

    this.swp = function(options) 
    { 
        this.callServer("SavePosition", [this.space,this.tab,options.startZone,options.currentZone,options.part,options.partCurrent,options.isUp,null]);
    };

    this.strings = {webPartLoadError:''};

    this.Load = function(options) {
        this.callServer("RenderWebPart", [this.space, this.tab, options.partId], {
            onOk: function(text) {
                var o = document.getElementById(options.clientId)
                if (o) {
                    o.innerHTML = text;
                   // zwpm._ajaxFix(options.partId);
                };
            },
            onError: function() {
                var o = document.getElementById(options.clientId)
                if (o) {
                    if (zwpm.strings.webPartLoadError) {
                        o.innerHTML = zwpm.strings.webPartLoadError;
                       // zwpm._ajaxFix(options.partId);
                    }
                };
            }
        });
    };
};

var zwpm = new ZebraWebPartManagerClass();
