/**
 * Copyright 2011 Internet Scout Project
 * http://scout.wisc.edu
 */

cw.provide("AteCentral", function(){

var Helpers = cw.require("CW-Helpers");

if (typeof jQuery == "undefined") {
    cw.error("jQuery is required for the AteCentral module");
}

function SimpleTruncate(string, maxLength) {
    var result = string;

    for (var i = maxLength; i < result.length; i++) {
        if (result.charAt(i).match(/\s+/)) {
            result = result.substr(0, i) + "...";
            break;
        }
    }

    return result;
}

function EventStore() {
    EventStore.base.call(this);
} cw.extend(EventStore, Helpers.RemoteDataStore);

EventStore.prototype.fetch = function(id, callback) {
    var store = this,
        parameters = {"ID": id, "Method": "GET", "ReturnType": "JSON"};

    $.getJSON(EventStore.ApiUrl, parameters, function(data){
        // cache the first object if available
        if (data.status.code == "OK" && data.data.numObjects > 0) {
            store.Cache[id] = data.data.objects[0];
            callback(store.Cache[id]);
        }
    });
};

EventStore.prototype.releaseEvent = function(id, callback) {
    var parameters = {"ID": id, "Released": 1,
        "Method": "PUT", "ReturnType": "JSON"};

    // so that the event will be re-fetched
    delete this.Cache[id];

    $.getJSON(EventStore.ApiUrl, parameters, callback);
};

EventStore.prototype.deleteEvent = function(id, callback) {
    var parameters = {"ID": id, "Method": "DELETE", "ReturnType": "JSON"};

    delete this.Cache[id];

    $.getJSON(EventStore.ApiUrl, parameters, callback);
};

/**
 * @const
 */
EventStore.ApiUrl = "index.php?P=EventApi";

function ResourceStore() {
    ResourceStore.base.call(this);
} cw.extend(ResourceStore, Helpers.RemoteDataStore);

ResourceStore.prototype.fetch = function(id, callback) {
    var parameters = {"id": id, "format": "json"},
        store = this;

    $.getJSON(ResourceStore.ApiUrl, parameters, function(data){
        if (data) {
            store.Cache[id] = data;
            callback(store.Cache[id]);
        }
    });
};

ResourceStore.ApiUrl = "index.php?P=ResourceAlternate";

function DefaultPopup(node, pointer, clobber) {
    DefaultPopup.base.call(this, node);

    this.Pointer = pointer;
    this.Clobber = clobber;

    // make sure the node isn't shackled to an element
    this.Node.remove();
    this.Node.appendTo("body");

    // make sure when it's off the screen and invisible
    DefaultPopup.base.prototype.hide.call(this);
    this.Node.css({"opacity": 0});

    var popup = this;

    // keep the popup shown when the mouse hovers over it
    this.Node.bind("mouseenter", function(){
        popup.Clobber(function(){}, {"delay": 0});
    });

    // allow the popup to be hidden when the mouse moves from it
    this.Node.bind("mouseleave", function(){
        popup.Clobber(function(){ popup.hide(); }, {"delay": 30});
    });
} cw.extend(DefaultPopup, Helpers.AnchoredPopup);

DefaultPopup.prototype.repositionPointer = function() {
    var popupHeight = this.Node.innerHeight(),
        pointerHeight = this.Pointer.innerHeight(),
        top = parseInt((popupHeight/2)-(pointerHeight/2), 10);

    this.Pointer.css("top", top);
};

DefaultPopup.prototype.show = function() {
    DefaultPopup.base.prototype.show.call(this);

    this.Node.animate({"opacity": "1"});
};

DefaultPopup.prototype.hide = function() {
    var popup = this,
        node = this.Node;

    node.animate({"opacity": "0"}, function(){
        DefaultPopup.base.prototype.hide.call(popup);
    });
};

DefaultPopup.prototype.Pointer = null;
DefaultPopup.prototype.Clobber = null;

function ResourcePopup(node, clobber) {
    var pointer = $(".ac-content-pointer", node);

    ResourcePopup.base.call(this, node, pointer, clobber);

    this.Title = $("p:first-child", this.Node);
    this.Description = $("p:nth-child(2)", this.Node);
} cw.extend(ResourcePopup, DefaultPopup);

ResourcePopup.prototype.attach = function(element, resource) {
    var _this = this

    this.setContent(resource, function(){
        _this.repositionPointer();
        _this.anchor(element, {"distance": 20, "anchorSide": "left"});
        _this.show();
    });
};

ResourcePopup.prototype.setContent = function(resource, onComplete) {
    this.setTitle(resource);
    this.setDescription(resource, onComplete);
};

ResourcePopup.prototype.setTitle = function(resource) {
    this.Title.html(resource.Title);
};

ResourcePopup.prototype.setDescription = function(resource, onComplete) {
    var $screenshot;
    var description = SimpleTruncate(resource.Description, 600),
        popup = this;

    this.Description.html(description);

    function addImage(url) {
        var $image = $("<img/>");

        $image.attr({"src": url, "alt": "Resource Image"});
        $image.css({
            "float": "left",
            "margin-right": "6px",
            "border": "1px solid #AAAAAA"});

        $image.load(function(){
            onComplete();
        });

        popup.Description.prepend($image);
    }

    if (resource.Screenshot) {
        addImage(resource.Screenshot);
    } else if (resource.SourceImage) {
        addImage(resource.SourceImage);
    } else {
        onComplete();
    }
};

ResourcePopup.prototype.Title = null;
ResourcePopup.prototype.Description = null;

function EventPopup(node, clobber) {
    var pointer = $(".ac-content-pointer", node);

    EventPopup.base.call(this, node, pointer, clobber);

    this.Name = $("p:first-child", this.Node);
    this.Description = $("p:nth-child(2)", this.Node);
    this.Swatch = $("p:nth-child(3) > span:first-child", this.Node);
    this.AteArea = $("p:nth-child(3) > span:nth-child(2)", this.Node);
    this.DataList = $("dl:last-child", this.Node);
} cw.extend(EventPopup, DefaultPopup);

EventPopup.prototype.attach = function(element, event) {
    this.setContent(event);
    this.repositionPointer();
    this.anchor(element, {"distance": 30, "anchorSide": "right"});
    this.show();
};

EventPopup.prototype.setContent = function(event) {
    this.setName(event);
    this.setDescription(event);
    this.setSwatch(event);
    this.setAteArea(event);
    this.setDataList(event);
};

EventPopup.prototype.setName = function(event) {
    this.Name.html((event.LongTitle !== "") ? event.LongTitle : event.Title);
};

EventPopup.prototype.setDescription = function(event) {
    var description = SimpleTruncate(event.Description, 600);

    this.Description.html(description);
};

EventPopup.prototype.setSwatch = function(event) {
    var swatch = event.Swatch,
        area = event.AteArea;

    if (area) {
        this.Swatch.css({"background-color": swatch});
        this.Swatch.show();
    } else {
        this.Swatch.hide();
    }
};

EventPopup.prototype.setAteArea = function(event) {
    var area = event.AteArea;

    if (area) {
        this.AteArea.html(area);
        this.AteArea.show();
    } else {
        this.AteArea.hide();
    }
};

EventPopup.prototype.setDataList = function(event) {
    var date;
    var days = Math.ceil((event.EndDate - event.StartDate)/86400)+1,
        list = this.DataList;

    function addPair(label, value) {
        list.append("<dt>"+label+"</dt>");
        list.append("<dd>"+value+"</dd>");
    }

    // remove existing children
    list.children().remove();

    // add location to data list if set
    if (event.Location !== "") {
        addPair("Location", event.Location);
    }

    // create date text
    if (days >= 2) {
        date = $.date("M jS, Y", {"timestamp":event.StartDate*1000});
        date += " - ";
        date += $.date("M jS, Y", {"timestamp":event.EndDate*1000});
        date += " ("+days+" days)";
    } else {
        date = $.date("M jS, Y", {"timestamp":event.StartDate*1000});
    }

    addPair("Date", date);
};

EventPopup.prototype.Name = null;
EventPopup.prototype.Description = null;
EventPopup.prototype.Swatch = null;
EventPopup.prototype.AteArea = null;
EventPopup.prototype.DataList = null;

function WhyLogInPopup(node, link, clobber) {
    var pointer = $(".ac-content-pointer", node);

    WhyLogInPopup.base.call(this, node, pointer, clobber);
} cw.extend(WhyLogInPopup, DefaultPopup);

WhyLogInPopup.prototype.attach = function(element) {
    this.repositionPointer();
    this.anchor(element, {"distance": 5, "anchorSide": "right"});
    this.show();
};

function ColorPickerPopup(node, clobber) {
    var pointer = $(".ac-content-pointer", node),
        popup = this;

    ColorPickerPopup.base.call(this, node, pointer, clobber);

    this.Node.unbind("mouseleave");

    // keep the popup shown when the mouse hovers over it
    this.Node.bind("click", function(){
        popup.Clobber(function(){}, {"delay": 0});
    });
} cw.extend(ColorPickerPopup, DefaultPopup);

ColorPickerPopup.prototype.attach = function(element) {
    this.repositionPointer();
    this.anchor(element, {"distance": 20, "anchorSide": "right"});
    this.show();
};

ColorPickerPopup.prototype.show = function() {
    DefaultPopup.base.prototype.show.call(this);

    this.Node.animate({"opacity": "1"}, 200);
};

ColorPickerPopup.prototype.hide = function() {
    var popup = this,
        node = this.Node;

    node.animate({"opacity": "0"}, 200, function(){
        DefaultPopup.base.prototype.hide.call(popup);
    });
};

function LinksPopup(node, anchor, clobber) {
    var popup = this;

    LinksPopup.base.call(this, node);

    this.Anchor = anchor;

    // make sure the node isn't shackled to an element
    this.Node.remove();
    this.Node.appendTo("body");

    // keep the popup shown when the mouse hovers over it
    this.Node.bind("mouseenter", function(){
        clobber(function(){}, {"delay": 0});
    });

    // allow the popup to be hidden when the mouse moves from it
    this.Node.bind("mouseleave", function(){
        clobber(function(){ popup.hide(); }, {"delay": 30});
    });
} cw.extend(LinksPopup, Helpers.AnchoredPopup);

LinksPopup.prototype.show = function() {
    var options = {
            "anchorSide": "bottom",
            "anchorHandle": 0,
            "popupHandle": 11};

    // different browsers require different distances :(
    if ($.browser.webkit) {
        options.distance = 7;
    } else if ($.browser.mozilla) {
        if (this.FirstShow) {
            options.distance = 9;
        } else {
            options.distance = 8;
        }
    } else if ($.browser.opera) {
        options.distance = 9;
    } else if ($.browser.msie) {
        if (parseInt($.browser.version, 10) == 8) {
            options.distance = 8;
        } else if (parseInt($.browser.version, 10) == 7) {
            options.distance = 17;
        } else {
            options.distance = 8;
        }
    } else {
        options.distance = 8;
    }

    this.anchor(this.Anchor, options);

    LinksPopup.base.prototype.show.call(this);

    if (this.FirstShow) {
        this.FirstShow = false;
    }
};

LinksPopup.prototype.anchor = function(anchor, options) {
    var popupTop, popupLeft;
    var windowWidth = $(window).width(),
        windowScrollLeft = $(window).scrollLeft(),
        popupWidth = this.Node.outerWidth(),
        popupHeight = this.Node.outerHeight(),
        sidePadding = 2;

    LinksPopup.base.prototype.anchor.call(this, anchor, options);

    popupTop = this.Node.offset()["top"];
    popupLeft = this.Node.offset()["left"];

    // make sure the links stay on screen
    if (popupWidth + popupLeft > windowWidth + windowScrollLeft) {
        popupLeft = windowWidth + windowScrollLeft - popupWidth - sidePadding;
        this.Node.offset({"top": popupTop, "left": popupLeft});
    } else if (popupLeft < windowScrollLeft) {
        popupLeft = windowScrollLeft + sidePadding;
        this.Node.offset({"top": popupTop, "left": popupLeft});
    }
};

LinksPopup.prototype.Anchor = null;
LinksPopup.prototype.FirstShow = true;

function Application() {
    this.EventStore = new EventStore();
    this.ResourceStore = new ResourceStore();
}

Application.prototype.main = function(document) {
    this.whyLogIn(document);
    this.colorPicker(document);
    this.quickEventEdit(document);
    this.microEventPopups(document);
    this.microResourcePopups(document);
    this.outreachKitDropdowns(document);
};

Application.prototype.whyLogIn = function(document) {
    var Clobber = $.clobber({"delay": 250}),
        Application = this;

    $(document).ready(function(){
        var $Link = $("#whylogin"),
            $WhyLogInPopup = $(".ac-content-whyloginpopup"),
            Popup;

        if ($WhyLogInPopup.length < 1 || $Link.length < 1) {
            return;
        }

        $Link.click(function(){
            return false;
        });

        $Link.css({
            "text-decoration": "none",
            "cursor": "default"
        });

        Popup = new WhyLogInPopup($WhyLogInPopup, $Link, Clobber);

        $Link.bind("mouseenter click", function(){
            var options = (Popup.isVisible()) ? {"delay": 60} : {};

            Clobber(function(){
                if (!Popup.isVisible()) {
                    Popup.attach($Link);
                }
            }, options);
        });

        $Link.mouseleave(function(){
            Clobber(function(){
                Popup.hide();
            }, {"delay": 30});
        });
    });
};

Application.prototype.colorPicker = function(document) {
    var Application = this;

    $(document).ready(function(){
        var $ColorPickerInputs = $(".ac-content-color"),
            $ColorPickerButtons = $(".ac-content-colorbutton"),
            $ColorPickerTemplate = $("#ac-content-colorpickerpopuptemplate");

        if ($ColorPickerButtons.length < 1 || $ColorPickerTemplate.length < 1) {
            return;
        }

        $ColorPickerButtons.each(function(){
            var Popup;
            var $button = $(this),
                $input = $(this).siblings(".ac-content-color"),
                $Popup = $ColorPickerTemplate.clone(),
                $Body = $(".cw-section-body", $Popup),
                $Colors = $(".cw-section-footer td", $Popup),
                Clobber = $.clobber({"delay": 250}),
                CircleDrag = false;

            // remove cloned id
            $Popup.attr("id", null);

            Popup = new ColorPickerPopup($Popup, Clobber);

            function onColorChange() {
                var fb = this;

                CircleDrag = fb.circleDrag;

                // transform a-f to A-F
                $input.each(function(){
                    this.value = this.value.toUpperCase();
                });
            }

            $Body.farbtastic({"element": $input, "callback": onColorChange});

            $(".farbtastic", $Body).click(function(){
                if (!CircleDrag) {
                    Popup.hide();
                }

                $input.focus();
            });

            $Colors.click(function(){
                var rgb = $("span", $(this)).css("background-color"),
                    hex = rgb2hex(rgb);

                $input.val(hex);
                $input.focus();
                $input.keyup();
                $input.change();

                Popup.hide();
            });

            $button.click(function(){
                var options = (Popup.isVisible()) ? {"delay": 60} : {};

                Clobber(function(){
                    if (!Popup.isVisible()) {
                        $input.focus();
                        Popup.attach($button);
                    }
                }, options);

                return false;
            });

            $input.blur(function(){
                if (!CircleDrag && !document.dragging) {
                    Clobber(function(){
                        Popup.hide();
                    }, {"delay": 30});
                }
            });
        });
    });

    function rgb2hex(rgb){
        var values = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);

        if (values) {
            return "#" +
                ("0" + parseInt(values[1],10).toString(16)).slice(-2) +
                ("0" + parseInt(values[2],10).toString(16)).slice(-2) +
                ("0" + parseInt(values[3],10).toString(16)).slice(-2);
        }

        values = rgb.match(/^rgba\((\d+),\s*(\d+),\s*(\d+),\s*(\d+)\)$/)

        if (values) {
            return "#" +
                ("0" + parseInt(values[1],10).toString(16)).slice(-2) +
                ("0" + parseInt(values[2],10).toString(16)).slice(-2) +
                ("0" + parseInt(values[3],10).toString(16)).slice(-2);
        }

        // didn't match, return color untouched
        return rgb;
    }
};

Application.prototype.microEventPopups = function(document) {
    var Clobber = $.clobber({"delay": 250}),
        Application = this;

    $(document).ready(function(){
        var $Events = $(".Event.Micro"),
            $EventPopup = $(".ac-content-eventpopup"),
            Popup;

        if ($EventPopup.length < 1 || $Events.length < 1) {
            return;
        }

        Popup = new EventPopup($EventPopup, Clobber);

        $Events.mouseenter(function(){
            var $source = $(this),
                options = (Popup.isVisible()) ? {"delay": 60} : {},
                id = $source.attr("objectid");

            $source.data("showPopup", true);

            Clobber(function(){
                Application.EventStore.get(id, function(event){
                    if ($source.data("showPopup")) {
                        Popup.attach($source, event);
                    }
                });
            }, options);
        });

        $Events.mouseleave(function(){
            var $source = $(this);

            $source.data("showPopup", false);

            Clobber(function(){
                Popup.hide();
            }, {"delay": 30});
        });
    });
};

Application.prototype.quickEventEdit = function(document) {
    var Application = this,
        confirmOptions = {"question":"Really?<br />", "or":"<br />or<br />"};

    $(document).ready(function(){
        var $Release = $(".Event .Release"),
            $Delete = $(".Event .Delete");

        // release event button actions
        $Release.confirm(function(){
            var source = $(this),
                event = source.parents(".Event"),
                id = source.attr("objectid");

            Application.EventStore.releaseEvent(id, function(data){
                if (data.status.code && data.status.code == "OK") {
                    source.remove();
                    $(".Unreleased", event).remove();
                } else {
                    alert(data.status.message);
                }
            });
        }, confirmOptions);

        // delete event button actions
        $Delete.confirm(function($clicked){
            var source = $(this),
                event = source.parents(".Event"),
                id = source.attr("objectid");

            Application.EventStore.deleteEvent(id, function(data){
                if (data.status.code && data.status.code == "OK") {
                    // get wrapper and event counter variables
                    var $wrapper = event.parents(".List");
                    var $count = $wrapper.children(".Header").children(".EventsCount");

                    // remove event-less sections
                    if (parseInt($count.html(), 10) <= 1) {
                        $parent = $wrapper.parents(".Events");
                        $wrapper.remove();

                        // if we deleted the last event
                        if ($parent.children().length <= 3) {
                            $noevents = $("<div/>");
                            $noevents.attr("class", "List").html("<p class=\"Header\">"+
                                "There are currently no events.</p>");
                            $("br", $parent).remove();
                            $parent.append($noevents);
                            $(".Events .OnBottom").remove();
                        }
                    } else {
                        $count.html((parseInt($count.html(), 10)-1)+"");
                    }

                    // remove the elements
                    event.remove();
                    $(".Separator[objectid="+id+"]").remove();
                }
            });
        }, confirmOptions);
    });
};

Application.prototype.microResourcePopups = function(document) {
    var Clobber = $.clobber({"delay": 250}),
        Application = this;

    $(document).ready(function(){
        var $Resources = $(".ac-content-resources.ac-content-micro .ac-content-resource"),
            $ResourcePopup = $(".ac-content-resourcepopup"),
            Popup;

        if ($ResourcePopup.length < 1 || $Resources.length < 1) {
            return;
        }

        Popup = new ResourcePopup($ResourcePopup, Clobber);

        $Resources.mouseenter(function(){
            var $source = $(this),
                options = (Popup.isVisible()) ? {"delay": 60} : {},
                id = parseInt($source.attr("resourceId"), 10);

            $source.data("showPopup", true);

            Clobber(function(){
                Application.ResourceStore.get(id, function(resource){
                    if ($source.data("showPopup")) {
                        Popup.attach($source, resource);
                    }
                });
            }, options);
        });

        $Resources.mouseleave(function(){
            var $source = $(this);

            $source.data("showPopup", false);

            Clobber(function(){
                Popup.hide();
            }, {"delay": 30});
        });
    });
};

Application.prototype.outreachKitDropdowns = function(document) {
    $(document).ready(function(){
        var $Links = $(".ac-outreachkit-links a");

        // change styles for links with dropdowns
        $Links.filter("[popup]").css({
            "cursor": "default",
            "text-decoration": "none"});

        $Links.each(function(){
            var popup;
            var clobber = $.clobber({"delay": 175}),
                $this = $(this),
                $popup = $("#"+$this.attr("popup"));

            if ($popup.length < 1) {
                return;
            }

            popup = new LinksPopup($popup, $this, clobber);

            $this.mouseover(function(){
                var options = popup.isVisible() ? {"delay": 60} : {"delay": 0};

                clobber(function(){
                    popup.show();
                }, options);
            });

            $this.mouseout(function(){
                clobber(function(){
                    popup.hide();
                }, {"delay": 30});
            });
        });
    });
};

Application.prototype.EventStore = null;
Application.prototype.ResourceStore = null;

// exports
this.EventStore = EventStore;
this.ResourceStore = ResourceStore;
this.DefaultPopup = DefaultPopup;
this.ResourcePopup = ResourcePopup;
this.EventPopup = EventPopup;
this.LinksPopup = LinksPopup;
this.Application = Application;

});

