Ultra.addNamespace('util');

/**
 *  PeriodicalExecuter
 *
 */
Ultra.util.PeriodicalExecuter = function(callback, frequency, defer) {

  var timer;

  var _this = {
    start: function() {
      if (!timer) {
        callback();
        timer = setInterval(_this.execute, frequency * 1000);
      }
    },
    execute: function() {
      if (timer) {
        callback();
      }
    },
    stop: function() {
      if (timer) {
        timer = clearInterval(timer);
      }
    }
  };

  if (!defer) {
    _this.start();
  }

  return _this;
};


/**
 *  Viewport
 *
 */
Ultra.util.Viewport = function() {

  var _getWindowWidth,
      _getWindowHeight,
      _getPageWidth,
      _getPageHeight,
      _getScrollLeft,
      _getScrollTop,
      _getScrollRight,
      _getScrollBottom,
      isInited = false;

  var init = function() {

    var documentElement = document.documentElement;
    var documentBody    = document.body;
  
    _getWindowWidth = function() {
      if (self.innerWidth) {
        return function() {
          return self.innerWidth;
        };
      } else if (documentElement && documentElement.clientWidth) {
        return function() {
          return documentElement.clientWidth;
        };
      } else if (documentBody) {
        return function() {
          return documentBody.clientWidth;
        };
      }
    }();
  
    _getWindowHeight = function() {
      if (self.innerHeight) {
        return function() {
          return self.innerHeight;
        };
      } else if (documentElement && documentElement.clientHeight) {
        return function() {
          return documentElement.clientHeight;
        };
      } else if (documentBody) {
        return function() {
          return documentBody.clientHeight;
        };
      }
    }();
  
    _getPageWidth = function() {
      if (documentBody.scrollWidth > documentBody.offsetWidth) {
        return function() {
          return documentBody.scrollWidth;
        };
      } else {
        return function() {
          return documentBody.offsetWidth;        
        };
      }
    }();
  
    _getPageHeight = function() {
      if (documentBody.scrollHeight > documentBody.offsetHeight) {
        return function() {
          return documentBody.scrollHeight;
        };
      } else {
        return function() {
          return documentBody.offsetHeight;        
        };
      }
    }();

    _getScrollLeft = function() {
      if (self.pageXOffset) {
        return function() {
          return self.pageXOffset;
        };
      } else if (documentElement && documentElement.scrollLeft) {
        return function() {
          return documentElement.scrollLeft;
        };
      } else if (documentBody) {
        return function() {
          return documentBody.scrollLeft;
        };
      }
    }();
  
    _getScrollTop = function() {
      if (self.pageYOffset) {
        return function() {
          return self.pageYOffset;
        };
      } else if (documentElement && documentElement.scrollTop) {
        return function() {
          return documentElement.scrollTop;
        };
      } else if (documentBody) {
        return function() {
          return documentBody.scrollTop;
        };
      }
    }();

    _getScrollRight = function() {
      return function() {
       return _getPageWidth() - (_getWindowWidth() + _getScrollLeft());
      };
    }();

    _getScrollBottom = function() {
      return function() {
       return _getPageHeight() - (_getWindowHeight() + _getScrollTop());
      };
    }();
  
    isInited = true;
  };

  // Public interface
  var _this = {

    getWindowWidth: function() {
      if (!isInited) {
        init();
      }
      return _getWindowWidth();
    },

    getWindowHeight: function() {
      if (!isInited) {
        init();
      }
      return _getWindowHeight();
    },

    getPageWidth: function() {
      if (!isInited) {
        init();
      }
      return _getPageWidth();
    },

    getPageHeight: function() {
      if (!isInited) {
        init();
      }
      return _getPageHeight();
    },

    getScrollLeft: function() {
      if (!isInited) {
        init();
      }
      return _getScrollLeft();
    },

    getScrollTop: function() {
      if (!isInited) {
        init();
      }
      return _getScrollTop();
    },

    getScrollRight: function() {
      if (!isInited) {
        init();
      }
      return _getScrollRight();
    },

    getScrollBottom: function() {
      if (!isInited) {
        init();
      }
      return _getScrollBottom();
    }
  };

  return _this;
}();








Ultra.util.CustomEvent = function(type, scope, signature) {
  this.type = type;
  this.scope = scope || window;
  this.signature = signature || Ultra.util.CustomEvent.LIST;
  this.subscribers = [];
};

Ultra.util.CustomEvent.LIST = 0;
Ultra.util.CustomEvent.FLAT = 1;

Ultra.util.CustomEvent.prototype = {
  
  subscribe: function(fn, obj, override) {
    this.subscribers.push(new Ultra.util.Subscriber(fn, obj, override));
  },

  count: function() {
    return this.subscribers.length;
  },

  fire: function() {

    var len = this.subscribers.length;

    if (len === 0) {
      return true;
    }

    var args = [],
        ret = true,
        i,
        rebuild = false;

    for (i = 0; i < arguments.length; ++i) {
      args.push(arguments[i]);
    }

    var argslength = args.length;
		var s;
    for (i = 0; i < len; ++i) {
      s = this.subscribers[i];
      if (!s) {
        rebuild = true;
      } else {
        var scope = s.getScope(this.scope);

        if (this.signature == Ultra.util.CustomEvent.FLAT) {
          var param = null;
          if (args.length > 0) {
            param = args[0];
          }
          ret = s.fn.call(scope, param, s.obj);
        } else {
          ret = s.fn.call(scope, this.type, args, s.obj);
        }
        if (ret === false) {
          return false;
        }
      }
    }

    if (rebuild) {
      var newlist = [],
          subs = this.subscribers;

      for (i = 0, len = subs.length; i < len; ++i) {
        s = subs[i];
        newlist.push(subs[i]);
      }

      this.subscribers = newlist;
    }

    return true;
  },
  
  unsubscribe: function(fn, obj) {    
    if (!fn) {
      return this.unsubscribeAll();
    }

    var found = false;
    for (var i = 0, n = this.subscribers.length; i < n; ++i) {
      var s = this.subscribers[i];
      if (s && s.contains(fn, obj)) {
        this._delete(i);
        found = true;
      }
    }
    return found;
  },

  unsubscribeAll: function() {
    for (var i = 0, n = this.subscribers.length; i < n; ++i) {
      this._delete(n - 1 - i);
    }
    this.subscribers = [];
    return i;
  },
  
  _delete: function(index) {
      var s = this.subscribers[index];
      if (s) {
        delete s.fn;
        delete s.obj;
      }
      this.subscribers[index] = null;
  }
  
};


/**
 *
 */
Ultra.util.Subscriber = function(fn, obj, override) {    
  this.fn       = fn;
  this.obj      = obj || null;
  this.override = override;
};  

Ultra.util.Subscriber.prototype = {
  
  getScope: function(defaultScope) {
    if (this.override) {
      if (this.override === true) {
        return this.obj;
      } else {
        return this.override;
      }
    }
    return defaultScope;
  },
  
  contains: function(fn, obj) {
    if (obj) {
      return (this.fn == fn && this.obj == obj);
    } else {
      return (this.fn == fn);
    }
  }
};







Ultra.util.addBBCodeTag = function(field, start_tag, value, end_tag) {

  field = $(field);

  field.setSelectedText(start_tag);
  var selection_start = field.getSelectionEnd();

  field.setSelectedText(value);
  var selection_end = field.getSelectionEnd();

  field.setSelectedText(end_tag);

  field.setSelectionRange(selection_start, selection_end);
}


/**
 *
 */
Ultra.util.addEmoticon = function(field, emoticon) {
  $(field).setSelectedText('[' + emoticon + ']');
};


/**
 *
 */
Ultra.util.addBBCodeImg = function(field, prompt_text) {

  if (typeof(prompt_text) == 'undefined') {
    prompt_text = 'Please enter the URL of your image:';
  }
  
  var value = prompt(prompt_text, 'http://');

  if (value !== null && value !== '') {
    var str = '[img]' + value + '[/img]';
    $(field).setSelectedText(str);
  }
};


/**
 *
 */
Ultra.util.addBBCodeUrl = function(field, prompt_text) {

  if (typeof(prompt_text) == 'undefined') {
    prompt_text = 'Please enter the URL of your link:';
  }
  
  var url = prompt(prompt_text, 'http://');

  if (url !== null && url !== '') {

    field = $(field);

    var start_tag = '[url="' + url + '"]';
    var value = $(field).getSelectedText();
    if (value.length === 0) {
      value = url;
    }
    var end_tag   = '[/url]';

    Ultra.util.addBBCodeTag(field, start_tag, value, end_tag);
  }
};


/**
 *
 */
Ultra.util.addBBCodeUser = function(field, prompt_text) {

  if (typeof(prompt_text) == 'undefined') {
    prompt_text = 'Please enter the username:';
  }
  
  var username = prompt(prompt_text);

  if (username !== null && username !== '') {

    var url = '/profile.php?user=' + username;
    var start_tag = '[url="' + url + '"]';
    var value = $(field).getSelectedText();
    if (value.length === 0) {
      value = url;
    }
    var end_tag   = '[/url]';

    Ultra.util.addBBCodeTag(field, start_tag, value, end_tag);
  }
};
 
 
/**
 *
 */
Ultra.util.addBBCodeBold = function(field) {

  var start_tag = '[b]';
  var value     = $(field).getSelectedText();
  var end_tag   = '[/b]';

  Ultra.util.addBBCodeTag(field, start_tag, value, end_tag);
};


/**
 *
 */
Ultra.util.addBBCodeItalic = function(field) {

  var start_tag = '[i]';
  var value     = $(field).getSelectedText();
  var end_tag   = '[/i]';

  Ultra.util.addBBCodeTag(field, start_tag, value, end_tag);
};


/**
 *
 */
Ultra.util.addBBCodeStrike = function(field) {

  var start_tag = '[s]';
  var value     = $(field).getSelectedText();
  var end_tag   = '[/s]';

  Ultra.util.addBBCodeTag(field, start_tag, value, end_tag);
};


/**
 *
 */
Ultra.util.addBBCodeUnderline = function(field) {

  var start_tag = '[u]';
  var value     = $(field).getSelectedText();
  var end_tag   = '[/u]';

  Ultra.util.addBBCodeTag(field, start_tag, value, end_tag);
};
