var Layout = {
  Center: function(element, parentElement, w)
  {
    if (Object.isElement(element)) {      
      var d = element.getDimensions();
      var pd;
      if ((Object.isElement(parentElement)) && (parentElement.getDimension)) {
        pd = parentElement.getDimension();
      } else {
        pd = Layout.GetWindowSize(w);        
      }
      var y = (pd.height - d.height) / 2;
      var x = (pd.width - d.width) / 2;

      element.setStyle({top: y + "px", left: x + "px", position: "absolute"});      
    }
  },  
  GetWindowSize: function(w) {
    var array = [];

    w = w ? w : window;
    array.width = array[0] = w.innerWidth || (w.document.documentElement.clientWidth || w.document.body.clientWidth);
    array.height = array[1] = w.innerHeight || (w.document.documentElement.clientHeight || w.document.body.clientHeight);

    return array;
  }  
}

var SimpleDialog = {
  InitializePage: function()
  {
    // not implemented  
  },
  Add: function(options)
  {
    var _options = options;
    var _visible = false;
    var _initialized = false;
    var _afterShowMethod = null;

    this.Show = _Show;
    this.Hide = _Hide;
    this.GetOptions = _GetOptions;

    _Initialize();

    function _Initialize()
    {
      if ((_options) && (!_initialized)) {
        for (var key in _options) {
          if (typeof _options[key] == "string") {
            _options[key] = $(_options[key]);
          }
        }

        if (typeof _options.Window == "undefined") {
          _options.Window = window;
        }
        
        _options.Opacity = _CorrectValue(_options.Opacity, 1.0);
        _options.ModalOpacity = _CorrectValue(_options.ModalOpacity, 0.7);
        _options.ModalShowDuration = _CorrectValue(_options.ModalShowDuration, 0.2);
        _options.ShowDuration = _CorrectValue(_options.ShowDuration, 0.2);
        _options.ModalHideDuration = _CorrectValue(_options.ModalHideDuration, 1.0);

        if (typeof _options.Modal != "boolean") {
          _options.Modal = true;
        }

        _initialized = true;
      }
    }

    function _GetOptions()
    {
      return _options;
    }
     
    function _Show(afterMethod)
    {
      if ((_initialized) && (!_visible) && (Object.isElement(_options.Element))) {
        _afterShowMethod = afterMethod;
        _visible = true;
        Event.observe(_options.Window, "resize", _OnResize);
        if (_options.Modal) {
          _MakeElementVisible(_GetModalElement(), _options.ModalOpacity,
            _options.ModalShowDuration, _ShowPhase2);
        } else {
          _ShowPhase2();
        }
      }
    }

    function _Hide(afterMethod)
    {
      if ((_initialized) && (_visible)) {
        _visible = false;
        Event.stopObserving(_options.Window, "resize", _OnResize);
        Element.hide(_options.Element);
        if (_options.Modal) {
          _MakeElementInvisible(_GetModalElement(), _options.ModalOpacity, _options.ModalHideDuration);
        }
        
        if (Object.isFunction(afterMethod)) {
          afterMethod()
        }
      }
    }

    function _GetVisible()
    {
      return _visible;
    }

    function _OnResize()
    {  
      Layout.Center(_options.Element, null, _options.Window);    
    }

    function _GetModalElement()
    {
      if (Object.isElement(_options.ModalElement)) {
        return _options.ModalElement;
      } else if (_options.Modal) {
        var p;
        if ((self.Proxy) && (Proxy.GetDefaultBodyFromContext) && (Proxy.GetContext)) {
          p = Proxy.GetDefaultBodyFromContext(Proxy.GetContext());
        } else {
          var bodylist = Element.select(document, "body");
          if (bodylist.length == 1) {
            p = bodylist[0];
          }
        }

        if (Object.isElement(p)) {
          var color = _options.ModalColor;
          if (typeof color == "undefined") {
            color = "#000000";
          }
          var zindex = _options.ModalZIndex;
          if (typeof zindex != "number") {
            zindex = 10000;
          }

          var element = new Element("div", { id: "modaldiv" });
          Element.hide(element);
          Element.setStyle(element, {
            zIndex: zindex,
            position: 'absolute',
            width: '100%',
            height: '100%',
            backgroundColor: color
          });
          p.appendChild(element);
          _options.ModalElement = element;
          return _options.ModalElement;
        } else {
          return null;
        }
      } else {
        return null;
      }
    }

    function _ShowPhase2()
    {
      _OnResize();
      _MakeElementVisible(_options.Element, _options.Opacity, _options.ShowDuration);
      if (Object.isFunction(_afterShowMethod)) {
        _afterShowMethod();
        _afterShowMethod = null;
      }
    }

    function _MakeElementVisible(element, opacity, _duration, after)
    {
      if (Object.isElement(element)) {
        if (self.Effect) {
          Effect.Appear(element, { from: 0.0, to: opacity, duration: _duration, afterFinish: after });
        } else {
          Element.show(element);
          if (typeof after == "function") {
            after();
          }
        }
      } else if (typeof after == "function") {
        after();
      }
    }

    function _MakeElementInvisible(element, opacity, _duration, after)
    {
      if (Object.isElement(element)) {
        if (self.Effect) {
          Effect.Fade(element, { duration: _duration, from: opacity, afterFinish: after });
        } else {
          Element.hide(element);
          if (typeof after == "function") {
            after();
          }
        }
      }
    }

    function _CorrectValue(value, defaultValue)
    {
      // Used to correct value for duraction and opacity
      if ((typeof value != "number") || (value < 0)) {
        if ((typeof defaultValue != "number") || (defaultValue <= 0)) {
          return 1.0;
        } else {
          return defaultValue;
        }
      } else {
        return value;
      }
    }
  }
}

var InputHint = {
  InitializePage: function()
  {
    var list = Element.select(document, "input[type='text']");
    list.each(function(input)
    {
      if (!InputHint.Assigned(input)) {
        var ignore = input.getAttribute("inputhintignore");
        if ((typeof ignore != "string") || (ignore != "true")) {
          new InputHint.Add(input,
            input.getAttribute("inputhint"),
            input.getAttribute("inputhintclass"));
        }
      }
    });
  },
  Assigned: function(element)
  {
    element = $(element);
    if ((Object.isElement(element)) && (typeof element.GetValue != "undefined")) {
      return true;
    } else {
      return false;
    }
  },
  Add: function(element, hint, inputHintClass)
  {
    InputHint.Create(element, { Hint: hint, HintClass: inputHintClass });
  },
  Create: function(element, options)
  {
    if (InputHint.Assigned(element)) {
      return;
    }
    
    if (typeof options == "undefined") {
      options = {};
    }    

    var _element = $(element);
    var _hasValue = false;
    options.Hint = _Trim(options.Hint);
    options.HintClass = _Trim(options.HintClass);
    if (options.HintClass.length == 0) {
      options.HintClass = "active";
    }

    this.GetValue = _GetValue;
    this.SetValue = _SetValue;
    this.HasValue = _HasValue;
    this.GetHint = _GetHint;
    this.SetHint = _SetHint;
    this.GetHintClass = _GetHintClass;
    this.SetHintClass = _SetHintClass;
    this.Clear = _Clear;

    _Initialize()

    function _Initialize()
    {
      if (_element) {
        Event.observe(_element, "blur", _OnBlur);
        Event.observe(_element, "focus", _OnFocus);
        Event.observe(_element, "keypress", _OnKeyPress);
        _element.GetValue = _GetValue;
        _element.SetValue = _SetValue;
        _element.HasValue = _HasValue;
        _element.GetHint = _GetHint;
        _element.SetHint = _SetHint;
        _element.GetHintClass = _GetHintClass;
        _element.SetHintClass = _SetHintClass;
        _element.Clear = _Clear;

        if (_Trim(_element.value).length == 0) {
          _element.value = options.Hint;
          _hasValue = false;
        } else {
          _hasValue = true;
        }
        _UpdateClass(!_hasValue);
      }
    }

    function _GetValue()
    {
      if ((_hasValue) && (_element)) {
        return _element.value;
      } else {
        return "";
      }
    }

    function _SetValue(value)
    {
      value = _Trim(value);
      if ((value.length > 0) && (_element)) {
        _element.value = value;
        _hasValue = true;
        _UpdateClass(false);
      }
    }

    function _HasValue()
    {
      return _hasValue;
    }

    function _GetHintClass()
    {
      return options.HintClass;
    }

    function _SetHintClass(value)
    {
      value = _Trim(value);
      if (value.length > 0) {
        if (!_hasValue) {
          _UpdateClass(false);
        }
        options.HintClass = value;
        if (!_hasValue) {
          _UpdateClass(true);
        }
      }
    }

    function _GetHint()
    {
      return options.Hint;
    }

    function _SetHint(value)
    {
      value = _Trim(value);
      if (_element) {
        options.Hint = value;
        if (!_hasValue) {
          _element.value = options.Hint;
        }
      }
    }

    function _Clear()
    {
      _hasValue = false;
      _element.value = options.Hint;
    }

    function _Trim(text)
    {
      if ((text) && (typeof text == "string")) {
        return text.replace(/^\s+|\s+$/g, '');
      } else {
        return "";
      }
    }

    function _OnBlur()
    {
      if (_Trim(_element.value).length == 0) {
        _element.value = options.Hint;
        _hasValue = false;
      } else {
        _hasValue = true;
      }
      _UpdateClass(!_hasValue)
    }

    function _OnFocus()
    {
      if (!_hasValue) {
        _element.value = "";
      }
      _UpdateClass(false);
    }

    function _OnKeyPress(event)
    {
      if (_Trim(_element.value).length == 0) {
        _hasValue = false;
      } else {
        _hasValue = true;
      }
    }

    function _UpdateClass(hintVisible)
    {
      if (hintVisible) {
        Element.addClassName(_element, options.HintClass);
      } else {
        Element.removeClassName(_element, options.HintClass);
      }
    }
  }
}

function SingleInstanceSupport(eventSink)
{
  var _eventSink = $(eventSink);

  this.Register = _register;
  this.Show = _show;
  this.HideAll = _hideAll;
  this.RegisterHideElement = _registerHideElement;
  
  function _register(id, hideMethod)
  { 
    if ((_eventSink) && (Object.isString(id)) && 
        (id != "") && (Object.isFunction(hideMethod))) {
      Event.observe(_eventSink, "knowmax:singleinstance", function(event) {                
        
        var isexcluded = false;
        if ((id == null) || (id != event.memo.Id)) {
        	if ((event.memo.ExcludeList) && (Object.isArray(event.memo.ExcludeList))) {       	  	
            for (var i=0; i < event.memo.ExcludeList.length; i++) {
        		  if (event.memo.ExcludeList[i] == id) {
        		    isexcluded = true;
        		    break;	
        		  }	
        		}
        	}        	                    
          if (!isexcluded) {
            hideMethod();	
          } 
        }                       
      });
    }
  }
   
  function _registerHideElement(element)
  {
    element = $(element);
    if (Object.isElement(element)) {
      Event.observe(element, "click", _hideAll);
    }
  }

  function _show(id)
  {    
    _fire(id);
  }
  
  function _hideAll(excludeList)
  {       
    _fire(null, excludeList);
  }
  
  function _fire(id, excludeList)
  {
    if ((_eventSink) && (_eventSink.fire)) {
      if ((Object.isString(id)) && (id == "")) {
        id = null;
      }
      _eventSink.fire("knowmax:singleinstance", {Id: id, ExcludeList: excludeList});
    }
  }
}

var Knowmax = {
  InputHint: InputHint,
  SimpleDialog: SimpleDialog,
  Layout: Layout,
  SingleInstanceSupport: SingleInstanceSupport
}

Event.observe(window, "load", _OnKnowmaxLoad);

function _OnKnowmaxLoad() 
{
  Knowmax.InputHint.InitializePage();
  Knowmax.SimpleDialog.InitializePage();
}