﻿/**
 * Modal - open modal/lightwindow window
 * @param options object
 */
BF.modal = function (options) {

    // scope alias
    var self = this;

    // setup defaults
    this.options = $.extend(true, {
        animate: true, // animate or not?
        animationDuration: 400, // time (in milliseconds) it takes to animate
        callbacks: { // callback functions
            afterClose: function () {}, // called after closing animation
            afterSetup: function () {}, // called after setup is complete
            beforeOpen: function () {}, // before open animation
            beforeClose: function () {} // before closing animation
        },
        content: 'inline', // content of modal, can be dynamic, confirmation or inline @TODO: implement ajax
        contentTarget: '', // if content is inline expects selector, otherwise it should be HTML (or text for confirmation)
        hideOnEsc: true, // hide modal on ESC key event
        hideOnOutsideClick: true, // hide modal on outside click?
        modalID: 'modal', // (base) CSS 
        triggers: '' // selectors that should trigger modal
    }, options || {});

    // instance variables
    this.modal = $('#' + this.options.modalID);
    this.overlay = $('#' + this.options.modalID + '-overlay');
    this.content = null;

    if (this.options.animate === false) {
        this.options.animationDuration = 0;
    }

    // privileged methods
    this.setup = function () {
        this.overlay = $('<div id="' + this.options.modalID + '-overlay"/>');
        this.modal = $('<div id="' + this.options.modalID + '"/>');

        if (this.options.content === 'inline') {
            // copy content
            this.content = $(this.options.contentTarget).clone();
            // check if cloned content wrapper has an id, in that case we need to change it
            if (this.content.attr('id')) {
                this.content.attr('id', this.options.modalID + '-' + $(this.options.contentTarget).attr('id'));
            }
            // check if children have ids
            var kids = this.content.find('*[id]');
            if (kids.length > 0) {
                for (var i = 0, l = kids.length; i < l; i++) {
                    $(kids[i]).attr('id', this.options.modalID + '-' + $(kids[i]).attr('id'));
                }
            }
        } else if (this.options.content === 'confirmation') {
            // create confirmation content
            this.content = $('<div class="' + this.options.modalID + '-confirmation" />');
            this.content.append(this.confirmationHeader);
            this.content.append('<p>' + this.options.contentTarget + '</p>');
            this.content.append(this.continueBtn);
        } else if (this.options.content === 'dynamic') {
            // build dynamic  
            this.content = $(this.options.contentTarget);
        } else {
            // @TODO: implement ajax
        }
        var closeBtn = $('<div id="' + this.options.modalID + '-close"/>');
        this.modal.append(closeBtn).append(this.content);
        $(document.body).append(this.overlay).append(this.modal);

        if (this.options.hideOnOutsideClick) {
            this.overlay.bind('click', function (e) {
                e.preventDefault();
                self.close();
            });
        }

        closeBtn.bind('click', function (e) {
            e.preventDefault();
            self.close();
        });

        // callback for afterSetup
        this.options.callbacks.afterSetup.call(this);
        $(document.body).trigger('BF:modal:setup'); // fire custom event

    };

    if (this.options.triggers !== '') {
        this.triggers = $(this.options.triggers);
        this.continueBtn = $('<a href="#" class="' + this.options.modalID + '-continue" target="_blank">Continue</a>');
        this.confirmationHeader = $('<h2></h2>');

        this.continueBtn.bind('click', function (e) {
            self.close();
        });

        this.triggers.live('click', function (e) {
            e.preventDefault();
            self.confirmationHeaderTxt = $(this).text();
            self.confirmationLnk = $(this).attr('href');
            self.open();
        });
    }

    // event handlers
    $(window).bind('resize', function () {
        self.position();
    });

    if (this.options.hideOnEsc) {
        $(document).bind('keydown', function (e) {
            e = e || window.event;
            switch (e.keyCode) {
                case 27: // esc
                    self.close();
                    break;
                default:
                    break;
            }
        });
    }

};

BF.modal.prototype = {

    close: function () {

        var self = this;

        // callback for beforeClose
        this.options.callbacks.beforeClose.call(this);

        this.overlay.fadeOut(this.options.animationDuration, function () {
            self.overlay.hide();
        });

        this.modal.fadeOut(this.options.animationDuration, function () {
            self.modal.hide();
            // callback for afterClose
            self.options.callbacks.afterClose.call(this);
        });

    },

    // create modal (if needed) and open it
    open: function () {

        var self = this, // scope alias
            content;

        // check if overlay already exists, if not, create it
        if (this.overlay.length !== 0) {
            // shouldn't have more than one modal window at a time, 
            // if so there's a problem
            // remove all but first (including all children)
            if (this.overlay.length > 1) {
                this.overlay.not(':first').remove();
                this.modal.not(':first').remove();
            }
        } else if ($('#' + this.options.modalID).length > 0) {
            // remove old stuff with same ID
            $('#' + this.options.modalID).remove();
            $('#' + this.options.modalID + '-overlay').remove();
            this.setup();
        }
        else {
            this.setup();
        }

        if (this.options.content === 'confirmation') {
            // update header and URL
            this.confirmationHeader.html(this.confirmationHeaderTxt);
            this.continueBtn.attr('href', this.confirmationLnk);
        }

        // callback for beforeOpen
        this.options.callbacks.beforeOpen.call(this);

        this.overlay.fadeIn(this.options.animationDuration * 2);
        this.position();
        this.modal.fadeIn(this.options.animationDuration * 2);

    },

    position: function () {
        this.modal.css({
            'left': ($(document.body).width() - this.modal.width()) / 2 + 'px',
            'top': ($(window).height() - this.modal.height()) / 2 + 'px'
        });
    }
};
