var Swish = Swish || {};
Swish.utils = (function() {
  
  return {
    setCookie: function(name,value,days) {
	    this.setCookieWithTime(name,value,(days*24*60*60*1000));
    },
    setCookieWithTime: function(name,value,time) {
	    if (time) {
		    var date = new Date();
		    date.setTime(date.getTime()+time);
		    var expires = "; expires="+date.toGMTString();
	    }
	    else var expires = "";
	    document.cookie = name+"="+value+expires+"; path=/";
    },
    getCookie: function(name) {
	    var nameEQ = name + "=";
	    var ca = document.cookie.split(';');
	    for(var i=0;i < ca.length;i++) {
		    var c = ca[i];
		    while (c.charAt(0)==' ') c = c.substring(1,c.length);
		    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	    }
	    return null;
    },
    deleteCookie: function(name) {
	    this.setCookie(name,"",-1);
    },
    printObject: function(obj) {
      var ret = "";
      for( prop in obj) {
        ret += prop + ": " + obj[prop] + "; ";
      }
      return ret;
    },
    arrayOfObjectsToObject: function(arr) {
      var ret = {};
      arr = arr || [];
      for( var i = 0; i < arr.length; i++ ) {
        var obj = arr[i];
        for( prop in obj) {
          ret[prop + i] = obj[prop];
        }
      }
      return ret;
    },
    formIdToObject: function(formidselector) {
        var obj = {}, fields = jq(formidselector).serializeArray();
        $.each(fields, function() {
            obj[this.name] = this.value;
        });
        return obj;
    },
    formToObject: function(form) {
        var obj = {}, fields = form.serializeArray();
        $.each(fields, function() {
            obj[this.name] = this.value;
        });
        return obj;
    },
    htmlEncode: function(toencode){ 
      return $('<div/>').text(toencode).html(); 
    },
    htmlDecode: function(todecode) {
      return $('<div/>').html(todecode).text(); 
    },
    reload: function() {
      location.href = location.href;
    },
    redirect: function(url) {
      location.href = url;
    },
    home: function() {
      location.href = "/";
    },
    arrayInArray: function(isArray, inArray) {
      var ret = true;
      if ( $.isArray(isArray) && $.isArray(inArray) ) {
        for( var i = 0; i < isArray.length; i++ ) {
          var item = isArray[i];
          if ( $.inArray(item, inArray) < 0 ) {
            ret = false;
          }
        }
      } else {
        ret = false;
      }
      return ret;
    },
    appendScript: function(url) {
      /*
      var e = document.createElement('script'); e.async = true;
      e.src = url;
      document.getElementById('swish-scripts').appendChild(e);
      */
      $("<script src=\"" + url + "\"></script>").appendTo("body");
    },
    noop: function() { return; }
  };
})();

Swish.ui = (function() {
  var _swash = {};
  var _xhrhandles = [];

  function _showSuccess(data) {
    if ( data.succ && data.fail ) {
      // show a succ vs failure dialog
      var title = data.title || "Finished";
      var info = $("<div/>", {title: title});
      if ( data.succ.length > 0 ) {
        var succ = $("<ul />");
        for ( var i = 0; i < data.succ.length; i++ ) succ.append($("<li />").html(data.succ[i]));
        info.append($("<div class=\"success\"/>").append("<h2>The following worked</h2>").append(succ));
      }
      if ( data.fail.length > 0 ) {
        var fail = $("<ul />");
        for ( var i = 0; i < data.fail.length; i++ ) fail.append("<li />").append(data.fail[i]);
        info.append($("<div class=\"failure\"/>").append("<h2>The following did not work</h2>").append(fail));
      }
      info.swishdialog({mode: "dialog", fade: 4000});
    }
  }

  function _showErrors(errs) {
	  if ( errs && errs.length > 0 ) {
		  for ( var i = 0; i < errs.length; i++ ) {
			
			  var err = errs[i];
			  var field = err.field;
			  var msg = err.msg;
			  var hascaptcha = false;

			  if ( field.length > 0 ) {
				  if ( field == "human" ) {
					  Swish.user.human();
				  } else {
					  _showError(field,msg);
					  if ( field == "recaptcha_response_field" ) {
						  setTimeout(function() { Swish.ui.captcha(msg) },50);
						  hascaptcha = true;
					  }
				  }
			  } else if ( msg.length > 0 ) {
				  Swish.ui.error(msg);
			  }
			  /* destroyed a different way now
			  if ( !hascaptcha ) {
				  $(".captcha").empty();
			  }
			  */
		  }
		  $(".bad:first").focus().select();
	  }
  }

  function _showError(field,msg) {
	  $("#" + field + "_err").html(msg);
	  $("#" + field + "_err").show();
	  $("#" + field).addClass("bad");
  }

  function _finishDialog(obj, event, params, callback) {
    obj.swishdialog(params);
    // need to stop propagation here because triggering event may end up closing the dialog
    if ( event ) event.stopPropagation();
    if ( $.isFunction(callback) ) callback();
  }

  function _fetchDialog(prefix, action, event, dialogParams, callback) {
    var $c = Swish.ui.get(action);
    if ( $c != null ) {
      _finishDialog($c, event, dialogParams, callback);
    } else {
      _xhrhandles[_xhrhandles.length] = $.get(
        prefix + action,
        function(response) {
          // separate out script content, else will try to create a dialog for it (oops)
          var $r = $(response);
          var dialogContent = $r.not('script');
          var scriptContent = $r.filter('script');            
          var contentId = dialogContent.attr("id") || "";
          var scriptsId = "swish-scripts-" + contentId;

          Swish.ui.put(action, dialogContent);
          _finishDialog(dialogContent, event, dialogParams);
          var scripts = $("#" + scriptsId);
          if ( scripts.size() > 0 ) {
            // nothing to be done
          } else {
            scripts = $("<div />", {id: scriptsId}).appendTo("body");
          }
          scriptContent.appendTo(scripts);
          if ( $.isFunction(callback) ) callback();
        },
        "html"
      );
    }
  }
  
  function _captcha() {
    //try {
      Recaptcha.create("6Lf2Zr4SAAAAAFEB3TrJnhhBJpNXipJmj3q9dAnv",
        "recaptcha_image",
        {
	        theme: "custom",
	        callback: function() {
	          $("#recaptcha_response_field").focus();
	        }
        }
      );
    //} catch ( ignored ) {}
  }

  return {
    get: function(key) {
      return _swash[key];
    },
    
    put: function(key, val) {
      _swash[key] = val;
    },
    
    gotoHelp: function(action) {
      var newwin = window.open("/info/" + action + "", "_blank");
    },

    getHelp: function(action, event, dialogParams, callback) {
      _fetchDialog("/pinfo/", action, event, dialogParams, callback);
    },

    getDialog: function(action, event, dialogParams, callback) {
      _fetchDialog("/axj/", action, event, dialogParams, callback);
    },
    
    loadDialog: function(action, event, dialogParams, callback) {
      var divparams = {"id": "swish-dialog-loader"};
      if ( dialogParams.minHeight ) {
        divparams.style = "min-height: " + dialogParams.minHeight + "; height: " + dialogParams.minHeight;
      }
      if ( dialogParams.height ) {
        divparams.style = "min-height: " + dialogParams.height + "; height: " + dialogParams.height;
      }
      var sd = $("#swish-dialog-loader");
      if ( sd.length == 0 ) {
        $("<div />", divparams).appendTo("body").swishdialog(dialogParams);
      }
      $("#swish-dialog-loader").load("/axj/" + action, callback).swishdialog("open");
      if ( event ) { 
        event.preventDefault();
        event.stopPropagation();
      }
    },
  
    closeDialogs: function() {
      for( key in _swash ) {
        try {
          Swish.ui.get(key).swishdialog("close");
        } catch (ignored) {}
      }
    },
    
    closeDialog: function(action) {
      var c = Swish.ui.get(action);
      if ( c != null ) {
        try {
          c.swishdialog("close");
        } catch (ignored) {}      
      }
    },

    confirm: function(msg, okmsg, callbacksuccess, dialogparams, cancelmsg, callbackcancel) {
      var okmsg = okmsg || "OK";
      var cancelmsg = cancelmsg || "Cancel";
      var dialogparams = dialogparams || {};
      var callbackcancel = callbackcancel || function() {};
      var params = $.extend({width: "400px", mode: "dialog", resizable: false, dialogClass: "swish-confirm", close: callbackcancel, closeOthers: false}, dialogparams);
      var btn = $("<a />",{"class":"btn","href":"javascript:void($.noop());"}).append(okmsg).button();
      var cancel = $("<span />", {"class":"aux"}).append($("<a />",{"href":"javascript:void($.noop());"}).append(cancelmsg));
      var dlg = $("<div/>", {"class": "swish-confirm"}).append(msg + "<br/><br/>").append(btn).append(cancel).swishdialog(params).css("min-height", 60);
      cancel.click(function(event) {
        //if ( $.isFunction(callbackcancel) ) callbackcancel(event);
        dlg.swishdialog("close")
      });
      btn.click(function(event) {
        dlg.swishdialog("option", "close", function() {});
        if ( $.isFunction(callbacksuccess) ) callbacksuccess(event);
        dlg.swishdialog("close");
      });
    },
    
    info: function(msg, dialogparams, callback) {
      var dialogparams = dialogparams || {};
      var callback = callback || Swish.utils.reload;
      var params = $.extend({width: "400px", minHeight: 60, mode: "dialog", resizable: false, fade: 1500, afterfade: callback, dialogClass: "swish-info", closeOthers: false}, dialogparams);
      if ( $("#swish-info").length > 0 ) {
        $("#swish-info").swishdialog("open");
      } else {
        $("<div/>", {id: "swish-info"}).append(msg).swishdialog(params);
      }
    },
    
    infoClose: function() {
      $("#swish-info").swishdialog("close");
    },

    wait: function(msg, dialogparams) {
      var msg = msg || "Updating...";
      var params = $.extend({uiInit: false, width: "400px", minHeight: 50, mode: "dialog", resizable: false, dialogClass: "swish-info swish-wait", closeOthers: false}, dialogparams);
      if ( $("#swish-wait").length > 0 ) {
        $("#swish-wait").swishdialog("open");
      } else {
        $("<div/>", {id: "swish-wait"}).append(msg).swishdialog(params);
      }
    },
    
    stopWaiting: function() {
      $("#swish-wait").swishdialog("close");
    },
    
    infoClose: function() {
      $("#swish-info").swishdialog("close");
    },
    
    error: function(msg) {
      alert(msg);
    },
    
    form: function(form, callbacksuccess) {
      var f = $(form);
      var id = f.attr("id") || "";
      var action = f.attr("action") || "";
      if ( id.length > 0 && action.length > 0 ) {
        var params = $.extend({action: action}, Swish.utils.formToObject(f));
        $("#" + id + " input.btn[type=submit]").button("disable");
        var after = function() {
          $("#" + id + " input.btn[type=submit]").button("enable");
        };
        Swish.ui.ajax(params, id, function(data) {
          after();
          if ( !$.isFunction(callbacksuccess) || callbacksuccess() !== false ) {
            _showSuccess(data);
          }
        }, function(data) {
          after();
          _showErrors(data.errors)
        });
      }
    },
    
    captcha: function(error) {
      // first clear out old captcha fields
      $(".captcha").empty();
      
      // hopefully there's only 1 captcha field visible
      var cfields = $(".captcha:visible");
      if ( cfields.length > 0 ) {
        var cfield = cfields.first();
        cfield.html("<span class=\"label\">Type the words you see below (prevents spam)</span><br/>"
            + "<div class=\"fielderror\" id=\"recaptcha_response_field_err\"></div>"
            + "<div id=\"recaptcha_image\"><br />loading...</div>"
            + "<input type=\"text\" id=\"recaptcha_response_field\" name=\"recaptcha_response_field\" value=\"\" style=\"width: 292px;\" /><br /><br />");
        if ( error ) {
          _showError("recaptcha_response_field",error);
        }
        //setTimeout(_captcha, 100);
        _captcha();
	    }
	    return false;
    },
  
    clearErrors: function() {
	    $(".fielderror").hide();
	    $("input").removeClass("bad");
	    return false;
    },
  
    // takes params object, calling method code, optional success/failure
    ajax: function(params, sig, callbacksuccess, callbackfailure) {
      var that = this;
	    _xhrhandles[_xhrhandles.length] = $.post(
		    "/axj/",
        params,
		    function(data) {
		      data = data || {};
	        if ( data.cookin && data.cookin.length > 0 ) {
		        Swish.utils.setCookie("sw_homemade",data.cookin,1000);
		        $("#captcha").hide();
	        }
	        if ( data.status && data.status === "OK" ) {
	          if ( data.hasresume && data.hasresume == "true" ) {
	            Swish.ui.ajax({action: "doResume"},"doResume",callbacksuccess,callbackfailure);
	            return;
	          }
	          if ( data.callback && $.isFunction(data.callback) ) {
	            callback(data);
	          } else {
	            if ( $.isFunction(callbacksuccess) ) {
	              callbacksuccess(data);
	            }
	            $(document).trigger(sig + ".success");
	            if ( data.redirect && data.redirect.length > 0 ) {
	              Swish.utils.redirect(data.redirect);
	            }
	          }
	        } else {
	          if ( $.isFunction(callbackfailure) ) {
	            callbackfailure(data);
	          } else if ( data.errors && data.errors.length > 0 ) {
  		        _showErrors(data.errors);
  		      } 
	          $(document).trigger(sig + ".failure");
	          
	        }
          $(document).trigger(sig + ".complete");
		    },
		    "json"
	    );
	    return false;
    },

    njax: function(params, callback) {
      var that = this;
	    _xhrhandles[_xhrhandles.length] = $.post(
		    "/axj/",
        params,
		    function(response) {
		      if ( $.isFunction(callback) ) {
		        callback(response);
		      }
		    },
		    "json"
	    );
	    return false;
    },

    setupListBuilder: function(id, listparams, autocompleteparams, callback) {
      var listparams = listparams || {};
      var autocompleteparams = autocompleteparams || {
        minLength: 3, delay: 5000, source: "/axj/?action=itemSearch",
        select: function(event, ui) {
          $("#swish-list" + id).swishlist("add", ui.item)
        },
        open: function(event, ui) {
          var curr = $("#addwishitem" + id).val();
          if ( curr.length == 0 ) {
            try {
              $("#addwishitem" + id).autocomplete("close");
            } catch (ignored) {}
          }
        },
        valueselect: function() {
          var name = Swish.utils.htmlEncode($("#addwishitem" + id).val().replace(/^\s*|\s*$/g,''));
          if ( name.length > 0 ) {
            var label = name;
            if ( name.length > 56 ) {
              label = name.substring(0,56) + "...";
            }
            $("#swish-list" + id).swishlist("add", {title:name, label:label, id:0, thumb:"", spid:0, price:""})
          }	  
        }
      }
      var swishlist = $("#swish-list" + id).swishlist(listparams)
      var swishcomplete = $("#addwishitem" + id).swishautocomplete(autocompleteparams);

      // setup other ui elements    
      $("#addbtn" + id).unbind("click").bind("click", function() {
        $("#addwishitem" + id).swishautocomplete("selectNonMenu").focus();
      });
      $("#submitlist" + id).unbind("click").bind("click", function(event) {
        var currlabel = $("#submitlist" + id).button("option", "label");
        $("#submitlist" + id).button("option", "label", "Going to your Wishlist...").button("disable");
        $(document).unbind("swish.list.add.failure").bind("swish.list.add.failure", function() {
          $("#submitlist" + id).button("option", "label", currlabel).button("enable");
          Swish.ui.stopWaiting();
        }).unbind("swish.list.add.success").bind("swish.list.add.success", function() {
          $("#submitlist" + id).button("enable");
        });
        Swish.ui.wait("Creating your Wishlist...");
        Swish.list.add("swish-list" + id);
        event.preventDefault();
        event.stopPropagation();
      });
      
      if ( $.isFunction(callback) ) {
        callback(swishlist, swishcomplete);
      }
    },
    
    init: function(context) {
      var ctx = context || document;
      $(".btn", ctx).button().removeClass("ui-state-focus");
      $(".btndis", ctx).button("disable");
      $(".swish-arrow-s", ctx).append("<div class=\"swish-icon-inner\"><img src=\"/images/swish-arrow-s.png\" /></div>");
      $(".options-link", ctx).hover(
        function() { $(this).toggleClass("options-link-hover"); },
        function() { $(this).toggleClass("options-link-hover"); }
      );
      $(".click-under", ctx).click(function(event) { event.preventDefault(); });
      $(".closeDialogs", ctx).click(function(event) { Swish.ui.closeDialogs(); });
      Swish.ui.captcha(); // should fire only if there's a visible captcha
    },
    
    centerInElement: function(inner, outer) {
      var o = $("#" + outer);
      var op = o.offset();
      var ow = o.outerWidth();
      var oh = o.outerHeight();
      var i = $("#" + inner);
      var iw = i.outerWidth();
      var ih = i.outerHeight();
      i.css("position","absolute").css("top", op.top + (oh/2 - ih/2)).css("left", op.left + (ow/2 - iw/2));
    },
    
    killAllAjax: function() {
      for( var i = 0; i < _xhrhandles.length; i++ ) {
        var handle = _xhrhandles[i];
        try {
          handle.abort();
        } catch (ignored) {}
      }
    }
  };
})();

Swish.user = (function() {
  return {
    human: function() {
      Swish.ui.getDialog("checkHuman.html", null, {width: '410px', mode: "dialog"});
    },
    afterLogout: function() {
      if ( Swish.logoutUrl && Swish.logoutUrl.length > 0 ) {
        location.href = Swish.logoutUrl;
      } else {
        Swish.utils.reload();
      }
    },
    logout: function(callback) {
      var callback = callback || Swish.user.afterLogout;
      $.post("/axj/", {action: "doLogout"}, function(data) {
		      Swish.utils.deleteCookie("sw_homemade");
	        callback();
	      },
	      "json"
      );
    },
    login: function(event) {
      Swish.ui.getDialog('doLogin.html', event, {width: '430px', positioning: 'under-left', of: '#mylogin', modal: true}, function() {
        FB.XFBML.parse(document.getElementById('doLogin'));
      })
    },
    signup: function(event) {
      Swish.ui.getDialog('doSignup.html', event, {width: '430px', positioning: 'under-left', of: '#mylogin', modal: true}, function() {
        FB.XFBML.parse(document.getElementById('doSignup'));
      })
    },
    forgot: function(event) {
      Swish.ui.getDialog('doForgot.html', event, {width: '360px', positioning: 'under-left', of: '#mylogin', modal: true})
    }
  };
})();

Swish.fb = (function() {
  return {
    getBaseperms: function() {
      return "email,publish_stream";
    },
    afterLogin: function(callback) {
      var logoutUrl = Swish.logoutUrl || "";
      Swish.ui.njax({action: "afterFbLogin", logoutUrl: logoutUrl}, function(data) {
        if ( $.isFunction(callback) ) {
          callback(logoutUrl);
        } else if ( data.logoutUrl ) {
          location.href = data.logoutUrl;
        } else {
          Swish.utils.reload();
        }
      });
    },
    login: function(perms, callbacknosession, callbacknoperms, callbacksuccess) {
      Swish.internalLogin = true;
      if ( perms == null ) perms = this.getBaseperms();
      FB.login(function(response) {
        if (response.session) {
          if (perms.length == 0 || response.perms) {
            if ( perms.length == 0 || Swish.utils.arrayInArray(perms.split(","), response.perms.split(",")) ) {
              Swish.fb.afterLogin(callbacksuccess);
            } else {
              if ( $.isFunction(callbacknoperms) ) callbacknoperms();
              else Swish.ui.info("Without permission from Facebook, we can't proceed.", {width: 600, fade: 2200, afterfade: $.noop});
            }
          } else {
            if ( $.isFunction(callbacknoperms) ) callbacknoperms();
              else Swish.ui.info("We will need your permission to continue.", {width: 500, fade: 2200, afterfade: $.noop});
          }
        } else {
          if ( $.isFunction(callbacknosession) ) callbacknosession();
          else Swish.ui.info("Please login to Facebook to continue.", {width: 600, fade: 2200, afterfade: $.noop});
        }
      }, {perms: perms});
    },
    logout: function(callback) {
      var callback = callback || function() {};
      FB.logout({cb: callback});
    },
    listenerShare: function(event, lid, lname, listid) {
      Swish.fb.login(
        "publish_stream",
        function() {
          Swish.ui.info("Please log in so we can let " + lname + "know the list is ready", {width: 700, fade: 3000, afterfade: $.noop});
          Swish.ui.njax({action: "enableListener", listenerid: lid, listid: listid}, $.noop);
        },
        function() {
          Swish.ui.info("Please give Swish permission to send a message saying your list is done.", {width: 700, fade: 3000, afterfade: $.noop});
          Swish.ui.njax({action: "enableListener", listenerid: lid, listid: listid}, $.noop);
        },
        function() {
          Swish.ui.njax({action: "enableListener", listenerid: lid, listid: listid}, function() {
            Swish.ui.njax({action: "notifyListener", listenerid: lid, listid: listid}, function() {
              Swish.ui.info("We let " + lname + " know that your wishlist is ready", {width: 700, fade: 3000, afterfade: $.noop});
            });
          });
        }
      );
      if ( event ) event.preventDefault();
    },
    picker: function(event, listid) {
      this.login(
        null,
        function() {
          Swish.ui.info("Please be sure to log in to Facebook to share with friends", {width: 700, fade: 3000, afterfade: $.noop});
        },
        function() {
          Swish.ui.info("Please give Swish permission to share your Wishlist", {width: 700, fade: 3000, afterfade: $.noop});
        },
        function() {
          Swish.ui.getDialog("friendPicker.html?listid=" + listid, event, {width: "800px", minHeight: 630, mode: "dialog"}, function() {
            $("#swish-scripts-friendPicker").appendTo($("#friendPickerFBML"));
            FB.XFBML.parse(document.getElementById('friendPicker'));
          });
        }
      );
      if ( event ) event.preventDefault();
    },
    collect: function(event) {
      this.login(
        null,
        function() {
          Swish.ui.info("Log into Facebook to start picking friends and family", {width: 700, fade: 3000, afterfade: $.noop});
        },
        function() {
          Swish.ui.info("Please give Swish permission to help choose friends", {width: 700, fade: 3000, afterfade: $.noop});
        },
        function() {
          Swish.ui.getDialog("friendCollect.html", event, {width: "800px", minHeight: 630, mode: "dialog"}, function() {
            var sc = $("#swish-scripts-friendCollect");
            var fc = $("#friendCollectFBML");
            sc.appendTo(fc);
            FB.XFBML.parse(document.getElementById('friendCollect'));
          });
        }
      );
      if ( event ) event.preventDefault();
    },
    publish: function(event, msg, actionlinks) {
      FB.ui({
          method: 'stream.publish',
          message: msg,
          action_links: actionlinks,
          user_message_prompt: 'Share your Swish suggestions'
        },
        function(response) {
          if (response && response.post_id) {
            Swish.ui.info("Your message was shared on Facebook - now let's see who responds... :)", {width: 750, fade: 2500, afterfade: $.noop});
          } else {
            Swish.ui.info("Facebook didn't accept your post for some reason. Try logging in with them first.", {width: 800, fade: 2500, afterfade: $.noop});
          }
        }
      );
      if ( event ) event.preventDefault();
    }
  };
})();

Swish.list = (function() {
  var sigfix = "swish.list";

  function _matchArrayToMap(matchable) {
    if ( $.isArray(matchable) ) {
      for ( var i = 0; i < matchable.length; i++ ) {
        matchlist[matchable[i]] = 0;
      }
    }
  }
  
  return {
    // takes a list object, goes to its page
    view: function(list) {
      location.href = "/" + list.code;
    },

    validateItems: function(listitems, listid, listuid, retry) {
      return true;
    },
  
    // takes the id of the list to add, returns false
    add: function(listuid) {
      var that = this;
      var list = $("#" + listuid); 
      var listitems = list.swishlist("list");
      var listid = list.swishlist("listid");
      if ( this.validateItems(listitems, listid, listuid, true) ) {
        var sig = sigfix + ".add";
        $(document).trigger(sig + ".before");
	      var params = $.extend({action: "addList", listid: listid, len: listitems.length}, Swish.utils.arrayOfObjectsToObject(listitems));
	      Swish.ui.killAllAjax();
	      Swish.ui.ajax(params, sig);
      }
	    return false;
    },
    
    newDialog: function(listuid, event) {
      var _list = null;
      var listuid = listuid || "";
      Swish.ui.getDialog('showAddToList.html?listid=0&listuid=' + listuid, event, {mode: "dialog", width: "720px", resizable: false, open: function() {
        Swish.ui.setupListBuilder(listuid, {style: "preview"}, null, function(list, autocomplete) {
          _list = list;
          var whennotempty = function() {
            $("#swish-pad" + listuid + " span.start b").html("Keep adding...");
            $("#swish-pad" + listuid + " span.start-details").html("Press Done when you are ready to start using your list");
            $("#submitlist" + listuid).button("option", "label", "Done - See my new Wishlist").button("enable");
          };
          var whenempty = function() {
            $("#swish-pad" + listuid + " span.start b").html("Start here <img src=\"/images/swish-arrow-s.png\" class=\"swish-arrow abg\" />");
            $("#swish-pad" + listuid + " span.start-details").html("Start typing to add items. Press Done to see your list. Try it and see how easy it is.");
            $("#submitlist" + listuid).button("option", "label", "Done - See my new Wishlist").button("enable");
          };
          list.unbind("swishlistnotempty").unbind("swishlistempty").bind("swishlistnotempty", whennotempty).bind("swishlistempty", whenempty);
        });
      }}, function() {
        var size = _list.swishlist("size");
        if ( size > 0 ) {
          _list.trigger("swishlistnotempty");
        } else {
          _list.trigger("swishlistempty");
        }
      });
    },

    addDialog: function(listuid, event) {
      var listid = $("#listid").val();
      var listuid = listuid || "";
      Swish.ui.getDialog('showAddToList.html?listid=' + listid + '&listuid=' + listuid, event, {mode: "dialog", width: "720px", resizable: false, open: function() {
        Swish.ui.setupListBuilder(listuid, {style: "preview", listid: listid}, null, function(list, autocomplete) {
          list.bind("swishlistnotempty", function() {
            $("#swish-pad" + listuid + " span.start b").html("Keep adding...");
            $("#swish-pad" + listuid + " span.start-details").html("Press Done when you are done adding new items");
            $("#submitlist" + listuid).button("option", "label", "Done - Go to my Wishlist").button("enable");
          }).bind("swishlistempty", function() {
            $("#swish-pad" + listuid + " span.start b").html("Add more items <img src=\"/images/swish-arrow-s.png\" class=\"swish-arrow abg\" />");
            $("#swish-pad" + listuid + " span.start-details").html("Start typing to add items you want. Press Done afterwards");
            $("#submitlist" + listuid).button("option", "label", "Done - Go to my Wishlist").button("enable");
          });
        });
      }});
    },
    
    matchDialog: function(itemidlist, event, isauto) {
      var action = "showItemOptions.html?itemid=" + itemidlist;
      if ( isauto ) action += "&auto=t";
      Swish.ui.getDialog(action, event, {width: '800px', mode: "dialog", height: 530, destroyOnClose: true, closeable: false,
          resizable: false, draggable: false});
      if ( event ) event.stopPropagation();
    },
    verifyInvite: function(listid) {
      Swish.ui.njax({action: "verifyInvite", listid: listid}, function(response) {
        if ( response.status == "OK" ) {
          Swish.ui.info("This list is now shared with you");
        } else {
          Swish.ui.confirm("Sorry, it seems that this Wishlist hasn't been shared with you yet.","Try again", function() { Swish.list.verifyInvite(); },
              {width: 600}, "Nevermind", function() { Swish.utils.home() });
        }
      });
    }
  };
})();

Swish.item = (function() {

  return {
    check: function(item, itemid, callback) {
      var itemid = itemid || "";
      var params = $.extend({action: "checkItem", itemid: itemid}, item);
      Swish.ui.njax(params, callback);
      return false;
    },
    skip: function(itemid, callback) {
      Swish.ui.njax({action: "skipItem", itemid: itemid}, callback);
    },
    claim: function(itemid, callback) {
      Swish.ui.confirm("CLAIM this item so that others know not to buy it?", "Claim this item", function() {
        Swish.ui.njax({action: "indBuy", itemid: itemid, type: "willbuy"}, callback);
      });
    },
    unclaim: function(itemid, callback) {
      Swish.ui.confirm("Unclaim this item so that it is available to others again?", "Unclaim", function() {
        Swish.ui.njax({action: "indBuy", itemid: itemid, type: "willbuy"}, callback);
      });
    },
    remove: function(itemid, callback) {
      Swish.ui.confirm("Are you sure you want to remove this from your Wishlist?","Remove this Item",function() {
        Swish.ui.njax({action: "removeItem",itemid: itemid}, callback);
      });
    },
    init: function(itemid, mode) {
      var mode = mode || "g";
      // big buy button
      $("#swish-item-buy-" + itemid).hover(function(event) {
        if ( buytimer != null ) {
          clearTimeout(buytimer);
        }
        Swish.ui.getDialog('showItemPrices.html?itemid=' + itemid, event, {width: '363px', topless: true, minHeight: 40, resizable: false, positioning: 'right-center', of: $(this), open: function() {
          $("#prices" + itemid).parent().hover(
            function() {
              if ( buytimer ) clearTimeout(buytimer);
            },
            function() {
              buytimer = setTimeout(function() {
                Swish.ui.closeDialog('showItemPrices.html?itemid=' + itemid);
              }, 500);
            }
          );  
        }});
      }, function(event) {
        buytimer = setTimeout(function() {
          Swish.ui.closeDialog('showItemPrices.html?itemid=' + itemid);
        }, 500);
      }).click(function(event) {
        event.stopPropagation();
      });
      if ( mode == "o" || mode == "v" ) {
        $("#swish-item-claim-" + itemid).click(function(event) {
          Swish.item.claim(itemid, function() {
            $("#swish-item-" + itemid).addClass("swish-item-claimed");
            $("#swish-item-claimed-msg-" + itemid).show();
            $("#swish-item-claim-" + itemid).hide();
            $("#swish-item-unclaim-" + itemid).show();
          });
          event.stopPropagation();
        });
        $("#swish-item-unclaim-" + itemid + ", #swish-item-unclaim-overlay-" + itemid).click(function(event) {
          Swish.item.unclaim(itemid, function() {
            $("#swish-item-" + itemid).removeClass("swish-item-claimed");
            $("#swish-item-claimed-msg-" + itemid).hide();
            $("#swish-item-claim-" + itemid).show();
            $("#swish-item-unclaim-" + itemid).hide();
          });
          event.stopPropagation();
        });
        Swish.ui.centerInElement("swish-item-claimed-msg-" + itemid, "swish-item-details-" + itemid);
        $(".swish-item-claimed-msg", "#swish-item-" + itemid + ".swish-item-claimed").show();
      }
      if ( mode == "o" ) {
        $("#swish-item-delete-" + itemid).click(function(event) {
          Swish.item.remove(itemid, function() {
            $("#swish-item-" + itemid).remove();
            $(".swish-item").each(function() {
              var iid = $(this).attr("itemid");
              $(".swish-item-claimed-msg", "#swish-item-" + iid + "").hide();
              $(".swish-item-claimed-msg", "#swish-item-" + iid + ".swish-item-claimed").show();
            });
          });
          event.stopPropagation();
        });
        $("#swish-item-photo-add-" + itemid).click(function(event) {
          Swish.list.matchDialog(itemid, event);
          event.stopPropagation();
        });
      }
      $("#swish-item-" + itemid).click(function(event) {
        Swish.ui.getDialog('showItemDetails.html?itemid=' + itemid, event, {width: '934px', resizable: false, mode: "dialog", open: function() {
          // do something after opening
        }});
      });
    },
    initDetail: function(itemid, mode) {
      var mode = mode || "g";
      if ( mode == "o" || mode == "v" ) {
        $("#swish-item-claim-det-" + itemid).click(function(event) {
          Swish.item.claim(itemid, function() {
            $("#swish-item-det-" + itemid).addClass("swish-item-claimed");
            $("#swish-item-claim-det-" + itemid).hide();
            $("#swish-item-unclaim-det-" + itemid).show();
            $("#swish-item-claim-details-det-" + itemid).show();
            $("#showItemDetails" + itemid).swishdialog("option", "close", Swish.utils.reload);
          });
          event.stopPropagation();
        });
        $("#swish-item-unclaim-det-" + itemid + ", #swish-item-claimed-details-unclaim-det-" + itemid).click(function(event) {
          Swish.item.unclaim(itemid, function() {
            $("#swish-item-det-" + itemid).removeClass("swish-item-claimed");
            $("#swish-item-claim-det-" + itemid).show();
            $("#swish-item-unclaim-det-" + itemid).hide();
            $("#swish-item-claim-details-det-" + itemid).hide();
            $("#showItemDetails" + itemid).swishdialog("option", "close", Swish.utils.reload);
          });
          event.stopPropagation();
        });
      }
      if ( mode == "o" ) {
        $("#swish-item-delete-det-" + itemid).click(function(event) {
          Swish.item.remove(itemid, function() {
            Swish.ui.info("Item deleted. Returning to Wishlist...", {width: 600, fade: 2500, afterfade: Swish.utils.reload});
          });
          event.stopPropagation();
        });
        $("#swish-item-title-det-" + itemid).inedit({params: {action: "renameItem", itemid: itemid}, title: "EDIT", doneVerb: "Done", maxWidth: 270, 
            hintClass: "oux", idSuffix: "item" + itemid, saveCallback: function() {
              $("#showItemDetails" + itemid).swishdialog("option", "close", Swish.utils.reload);
            }});
        $("#swish-item-description-edit-form-det-" + itemid).unbind("submit").bind("submit", function(event) {
          Swish.ui.form("#swish-item-description-edit-form-det-" + itemid, function() {
            $("#swish-item-description-edit-form-det-" + itemid).hide();
            $("#swish-item-description-change-det-" + itemid).show();
            var val = $("#swish-item-description-edit-det-" + itemid).val().replace(/\n/g,"<br />");
            $("#swish-item-description-det-" + itemid).html(val).show();
            $("#showItemDetails" + itemid).swishdialog("option", "close", Swish.utils.reload);
          });
          event.stopPropagation();
          event.preventDefault();
        });
        $("#swish-item-description-edit-cancel-det-" + itemid).unbind("click").bind("click", function(event) {
          $("#swish-item-description-det-" + itemid).show();
          $("#swish-item-description-edit-form-det-" + itemid).hide();
          $("#swish-item-description-change-det-" + itemid).show();
          event.stopPropagation();
        });
        $("#swish-item-description-change-det-" + itemid).unbind("click").bind("click", function(event) {
          $("#swish-item-description-edit-form-det-" + itemid).show();
          $("#swish-item-description-change-det-" + itemid).hide();
          $("#swish-item-description-det-" + itemid).hide();
          event.stopPropagation();
        });
        $("#swish-item-rematch-switch-det-" + itemid).unbind("click").bind("click", function(event) {
          Swish.ui.confirm("If you think the photos, prices and other details that were added to your item are wrong, you can try again to match them to a product that Swish knows about.",
              "Continue - Find correct item", function() {
            Swish.ui.njax({action: "unmatchItem", itemid: itemid}, Swish.utils.reload);
          });
          event.stopPropagation();
        });
        $("#swish-item-prices-track-det-" + itemid).unbind("click").bind("click", function(event) {
          Swish.ui.njax({action: "unmatchItem", itemid: itemid}, Swish.utils.reload);
          event.stopPropagation();
        });
        $("#swish-item-photo-add-det-" + itemid).unbind("click").bind("click", function(event) {
          Swish.ui.confirm("Swish can automatically add photos, prices and more.<br />Just start by quickly ensuring we have the right item.",
              "Ensure we have the right item", function() {
            Swish.ui.njax({action: "unmatchItem", itemid: itemid}, Swish.utils.reload);
          }, {width: 410});
          event.stopPropagation();
        });
      }
    }
  };
})();

$.widget("ui.inedit", {
  // default options
  options: {
    state: "off",
    form: null,
    editor: null,
    title: "Click to edit",
    params: null, // params to be sent on submit/done
    action: null,
    doneVerb: "Rename Wishlist",
    hint: null,
    maxWidth: 700,
    hintClass: "swish-edit-hint",
    idSuffix: "",
    saveCallback: null
  },
  _create: function() {
    // can use this.options and this.element
    var that = this;
    var wide = this.element.width() + 50;
    if ( wide < 200 ) wide = 200;
    if ( wide > this.options.maxWidth ) wide = this.options.maxWidth;
    var height = this.element.height();
    var fsize = this.element.css("font-size");
    var lheight = (height - 4) + "px";
    var ffamily = this.element.css("font-family");
    var fweight = this.element.css("font-weight");
    this.options.editor = $("<input />", {
      type:"text",id:"ui-inedit-edit" + this.options.idSuffix,"class":"ui-inedit-edit"
    }).css("width", (wide + 10)).css("line-height", lheight).css("font-size", fsize).css("font-weight", fweight).css("margin-top", -1)
      .css("margin-left", -1).css("padding-bottom", 1).css("font-family",ffamily);
    var donebtn = $("<input />", {type: "submit", value: this.options.doneVerb}).css("vertical-align", "middle").css("margin-top", -1).button();
    var cancelbtn = $("<a />", {"class": "aux","href": "javascript:void(Swish.utils.noop());"}).append("Cancel").click(function() { that.stop(); });
    this.options.form = $("<form />",{"class":"ui-inedit-form"}).css("height", height)
        .append(this.options.editor)
        .append(donebtn)
        .append(cancelbtn)
        .submit(function(event) {
          that.doDone();
          event.preventDefault();
        });
    this.options.hint = $("<div />", { id: "ui-inedit-hint" + this.options.idSuffix, "class": this.options.hintClass }).html(this.options.title).click( function() { that.start(); });
    var wrapper = $("<div />", { id: "ui-inedit-root" + this.options.idSuffix, "class": "ui-inedit-container swish-edit-hint-parent" });
    this.element.addClass("ui-inedit").wrap(wrapper).click(function() { that.start(); });
    this.element.parent().append(this.options.hint);
    if ( this.options.state == "off" ) {
      this.options.form.hide();
    }
    this.element.parent().append(this.options.form);
    this.element.attr("title",this.options.title);
    var action = this.element.attr("action") || "";
    if ( action.length > 0 ) {
      this.options.action = action;
    }
  },
  start: function() {
    this.options.editor.val(this.element.text());
    this.element.hide();
    this.options.hint.hide();
    this.options.form.show();
    this.options.editor.focus().select();
  },
  stop: function() {
    this.element.show();
    this.options.hint.show();
    this.options.form.hide();
  },
  doDone: function() {
    var currval = Swish.utils.htmlEncode($.trim(this.options.editor.val()));
    if ( this.options.params != null && currval.length > 0 ) {
      Swish.ui.njax($.extend({}, this.options.params, {"value": currval}), this.options.saveCallback);
    }
    this.element.html(this.options.editor.val());
    this.stop();
    return false;
  }
});

$.widget("ui.swishlist", {
  // an item has { id:1, name:"ipod", description: "desc", thumb, image, lowprice }
  // default options
  options: {
    style: "normal", /* normal or preview */
    items: [],
    listid: 0
  },
  _makeItemPreview: function(item, num) {
    var that = this;
    var thumb = item.thumb.length == 0 ? "" : "<img src=\"" + item.thumb + "\" />";
    var price = "";
    if ( item.price && item.price.length > 0 ) {
      try {
        price = "&#36;" + parseInt(item.price,10);
      } catch(ignored) {}
    }
    var close = $("<div />", {"class":"hc swish-item-right swish-item-delete",del:num})
        .click(function() {
          that.remove(num);
        }).html("X");

    return $("<li id=\"swish-item" + num + "\" class=\"fbg swish-item rbox item\"></li>")
      .append("<div class=\"fbg hc swish-item-left\">" + num + "</div>")
      .append(close)
      .append("<div class=\"gbg rbox swish-item-details\"><div class=\"link price\">" + price + "</div><div class=\"pic\">" + thumb + "</div>" + item.label + "</div>");
  },
  _makeItem: function(item, num) {
    if ( this.options.style == "preview" ) {
      return this._makeItemPreview(item, num);
    } else {
      return this._makeItemNormal(item, num);
    }
  },
  _clearListUI: function() {
    this.element.empty();
  },
  _appendItemUI: function(item, num) {
    this.element.append(this._makeItem(item,num)).show();
  },
  _updateItemUI: function(item, idx) {
    var thumb = item.thumb.length == 0 ? "" : "<img src=\"" + item.thumb + "\" />";
    var price = "";
    if ( item.price && item.price.length > 0 ) {
      try {
        price = "&#36;" + parseInt(item.price,10);
      } catch(ignored) {}
    }

    $("#swish-item" + (idx + 1) + " div.price").html(price);
    $("#swish-item" + (idx + 1) + " div.pic").html(thumb);
  },
  _updateSize: function() {
    if ( this.options.items.length == 0 ) {
      this._trigger("empty");
    } else {
      this._trigger("notempty");
    }
  },
  _create: function() {
    // can use this.options and this.element
    var that = this;
    this.element.addClass("swish-list");
    if ( this.options.style == "preview" ) {
      this.element.addClass("swish-list-preview");
    }
    if ( this.options.items.length == 0 ) {
      this.element.hide();
    } else {
      for ( var i = 0; i < this.options.items.length; i++ ) {
        
      }
    }
  },
  update: function(idx, wi) {
    if ( wi.spid || wi.pgid ) wi.prod = 1;
    else wi.prod = 0;
    this.options.items[idx] = wi;
    this._updateItemUI(wi, idx);
    this._trigger("update");
  },
  skip : function(idx) {
    this.options.items[idx].prod = 2;
    this._trigger("update");
  },
  skipAll : function() {
    for ( var i = 0; i < this.options.items.length; i++ ) {
      if ( this.options.items[i].prod = 0 ) {
        this.options.items[idx].prod = 2;
      }
    }
    this._trigger("update");
  },
  add: function(wi) {
    if ( wi.spid || wi.pgid ) wi.prod = 1;
    else wi.prod = 0;
    this.options.items.push(wi);
    this._appendItemUI(wi, this.options.items.length);
    Swish.item.check(wi);
    this._updateSize();
    this._trigger("add");
  },
  refresh: function() {
    this._clearListUI();
    for ( var i = 0; i < this.options.items.length; i++ ) {
      var item = this.options.items[i];
      this._appendItemUI(item, (i + 1));
    } 
  },
  size: function() {
    return this.getSize();
  },
  getSize: function() {
    return this.options.items.length;
  },
  list: function() {
    return this.options.items;
  },
  listid: function() {
    return this.options.listid;
  },
  remove: function(idx) {
    this.options.items.splice((idx - 1), 1);
    this.refresh();
    this._updateSize();
    this._trigger("remove");
  }
});

$.widget("ui.swishautocomplete", $.extend({}, $.ui.autocomplete.prototype, {
  options: $.extend({}, $.ui.autocomplete.prototype.options, {
    valueselect: $.noop, // callback for what to do
    afterselect: $.noop,
    queue: [], // next items to autocomplete with
    stubborn: false, // only closes if destroyed or slammed
    clearAfterEnter: true 
  }),
  _renderItem: function( ul, item ) {
    var thumb = item.thumb.length == 0 ? "" : "<img src=\"" + item.thumb + "\" />";
    var price = "";
    if ( item.price && item.price.length > 0 ) {
      try {
        price = "&#36;" + parseInt(item.price,10);
      } catch(ignored) {}
    }
	  return $( "<li></li>" )
		  .data( "item.autocomplete", item )
		  .append( "<a><div class=\"pic\">" + thumb + "</div><div class=\"price\">" + price + "</div>" + item.label + "</a>" )
		  .appendTo(ul);
  },
  selectNonMenu: function() {
    if (this.xhr) {
			this.xhr.abort();
		}
    this.options.valueselect(this.element.val());
    if ( this.options.clearAfterEnter ) {
      this.element.val("");		
    }
    this.close();
  },
  close: function() {
    if ( !this.options.stubborn ) {
      $.ui.autocomplete.prototype.close.call(this);    
    }
  },
  slam: function() {
    $.ui.autocomplete.prototype.close.call(this);    
  },
  _create: function() {
		var self = this,
			doc = this.element[ 0 ].ownerDocument;

		this.element
			.addClass( "ui-autocomplete-input" )
			.attr( "autocomplete", "off" )
			// TODO verify these actually work as intended
			.attr({
				role: "textbox",
				"aria-autocomplete": "list",
				"aria-haspopup": "true"
			})
			.bind( "keydown.autocomplete", function( event ) {
				if ( self.options.disabled ) {
					return;
				}

				var keyCode = $.ui.keyCode;
				switch( event.keyCode ) {
				case keyCode.PAGE_UP:
					self._move( "previousPage", event );
					break;
				case keyCode.PAGE_DOWN:
					self._move( "nextPage", event );
					break;
				case keyCode.UP:
					self._move( "previous", event );
					// prevent moving cursor to beginning of text field in some browsers
					event.preventDefault();
					break;
				case keyCode.DOWN:
					self._move( "next", event );
					// prevent moving cursor to end of text field in some browsers
					event.preventDefault();
					break;
				case keyCode.ENTER:
				case keyCode.NUMPAD_ENTER:
					// when menu is open or has focus
					if ( self.menu.element.is( ":visible" ) ) {
						event.preventDefault();
					}
					//passthrough - ENTER and TAB both select the current element
				case keyCode.TAB:
					if ( !self.menu.active ) {
            self.selectNonMenu();
					} else {
  					self.menu.select( event );
            if ( self.options.clearAfterEnter ) {
              self.element.val("");		
            }
          }
					break;
				case keyCode.ESCAPE:
					self.element.val( self.term );
					self.close( event );
					break;
				default:
					// keypress is triggered before the input value is changed
					clearTimeout( self.searching );
					self.searching = setTimeout(function() {
						// only search if the value has changed
						if ( self.term != self.element.val() ) {
							self.selectedItem = null;
							self.search( null, event );
						}
					}, self.options.delay );
					break;
				}
			})
			.bind( "focus.autocomplete", function() {
				if ( self.options.disabled ) {
					return;
				}

				self.selectedItem = null;
				self.previous = self.element.val();
			})
			.bind( "blur.autocomplete", function( event ) {
				if ( self.options.disabled ) {
					return;
				}

				clearTimeout( self.searching );
				// clicks on the menu (or a button to trigger a search) will cause a blur event
				self.closing = setTimeout(function() {
					self.close( event );
					self._change( event );
				}, 150 );
			});
		this._initSource();
		this.response = function() {
			return self._response.apply( self, arguments );
		};
		this.menu = $( "<ul></ul>" )
			.addClass( "ui-autocomplete" )
			.appendTo( $( this.options.appendTo || "body", doc )[0] )
			// prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
			.mousedown(function( event ) {
				// clicking on the scrollbar causes focus to shift to the body
				// but we can't detect a mouseup or a click immediately afterward
				// so we have to track the next mousedown and close the menu if
				// the user clicks somewhere outside of the autocomplete
				var menuElement = self.menu.element[ 0 ];
				if ( event.target === menuElement ) {
					setTimeout(function() {
						$( document ).one( 'mousedown', function( event ) {
							if ( event.target !== self.element[ 0 ] &&
								event.target !== menuElement &&
								!$.ui.contains( menuElement, event.target ) ) {
								self.close();
							}
						});
					}, 1 );
				}

				// use another timeout to make sure the blur-event-handler on the input was already triggered
				setTimeout(function() {
					clearTimeout( self.closing );
				}, 13);
			})
			.menu({
				focus: function( event, ui ) {
					var item = ui.item.data( "item.autocomplete" );
					if ( false !== self._trigger( "focus", null, { item: item } ) ) {
						// use value to match what will end up in the input, if it was a key event
						if ( /^key/.test(event.originalEvent.type) ) {
							self.element.val( item.value );
						}
					}
				},
				selected: function( event, ui ) {
					var item = ui.item.data( "item.autocomplete" ),
						previous = self.previous;

					// only trigger when focus was lost (click on menu)
					if ( self.element[0] !== doc.activeElement ) {
						self.element.focus();
						self.previous = previous;
					}

					if ( false !== self._trigger( "select", event, { item: item } ) ) {
						self.term = item.value;
					}
				  self.element.val("");

					self.close( event );
					self.selectedItem = item;

					if ( false !== self._trigger( "afterselect", event, { item: item } ) ) {
						//self.term = item.value;
					}
				},
				blur: function( event, ui ) {
					// don't set the value of the text field if it's already correct
					// this prevents moving the cursor unnecessarily
					if ( self.menu.element.is(":visible") &&
						( self.element.val() !== self.term ) ) {
						self.element.val( self.term );
					}
				}
			})
			.zIndex( this.element.zIndex() + 1 )
			// workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
			.css({ top: 0, left: 0 })
			.hide()
			.data( "menu" );
		if ( $.fn.bgiframe ) {
			 this.menu.element.bgiframe();
		}
	}
}));

$.widget("ui.swishdialog", $.extend({}, $.ui.dialog.prototype, {
  options: $.extend({}, $.ui.dialog.prototype.options, {
    mode: "popover", // popover (clear non-modal), dialog (modal), tooltip (clear hover non-modal)
    positioning: "", // right (right w h. flip), left (left w h. flip), under (bottom w lefts aligned), under-left (bottom w rights aligned)
    of: null, // item to position around
    focusfirst: true, // focus on first input element in dialog once open
    fade: 0, // if positive int, will set a timeout and destroy dialog after
    afterfade: null, // callback after "fading"
    closeable: true,  // whether or not to show the close button
    destroyOnClose: false, // auto-destroy on close or no?
    closeOthers: true, // close other dialogs on open by default
    uiInit: true, // initialize ui elements inside the dialog once opened
    topless: false // omit the header altogether
  }),
  _instances: [],
  _create: function() {
    if ( this.options.mode == "dialog" ) {
      this.options.modal = true;
    }
    if ( !this.options.closeable ) {
      this.options.dialogClass += " swish-dialog-noclose";
    }
    if ( this.options.topless ) {
      this.options.dialogClass += " swish-dialog-notop";
    }
    $.ui.dialog.prototype._create.call(this);
    this._instances.push(this.element);
  },
  _init: function() {
    $.ui.dialog.prototype._init.call(this);
  },
  open: function() {
    var self = this;
    if ( this.options.closeOthers ) {
      // only 1 at a time open - and let's use _instances so as not to traverse DOM
      var otherInstances = $.grep(this._instances, function(elem) { 
          return elem !== this.element;
	    });
      $.each(otherInstances, function() {
        var me = $(this);
		    if( me.dialog("isOpen") ) {
          me.dialog("close");
        }
      });
    }
    // super
    $.ui.dialog.prototype.open.call(this);
    // positioning shortcuts
    this.options.of = this.options.of || "";
    var pos = {my: "left top", at: "right top"};
    if ( this.options.of.length > 0 && this.options.positioning.length > 0 ) {
      if ( this.options.positioning == "left" ) {
        pos = {my: "right top", at: "left top"};
      } else if ( this.options.positioning == "under" ) {
        pos = {my: "left top", at: "left bottom"};
      } else if ( this.options.positioning == "under-left" ) {
        pos = {my: "right top", at: "right bottom"};
      } else if ( this.options.positioning == "right-center" ) {
        pos = {my: "left center", at: "right center"};
      }
      pos.of = this.options.of;
      pos.collision = "flip fit";
      this.element.parent().position(pos);
    }
    // close on outside click
    if ( this.options.mode == "popover" ) {
      $("body").click(function() {
        self.close();
      });
      this.element.parent().click(function(event) {
        event.stopPropagation();
      });
    }
    // re-init common styles (for new elements added to DOM)
    if ( this.options.focusfirst ) {
      $(".ui-dialog input:first").focus();
    }
    if ( this.options.uiInit ) {
      Swish.ui.init(self.element);
    }
    if ( this.options.fade && this.options.fade > 0 ) {
      setTimeout(function() {
        self.close();
        if ( $.isFunction(self.options.afterfade) ) {
          self.options.afterfade();
        }
      }, this.options.fade);
    }
  },
  close: function() {
    // super
    this._trigger("beforeclose");
    if ( $("#recaptcha_image", this.element).size() > 0 ) {
      Recaptcha.destroy();
    }
    if ( this.options.destroyOnClose ) {
      $.ui.dialog.prototype.destroy.call(this);    
      this.element.remove();
    } else {
      $.ui.dialog.prototype.close.call(this);
    }
    // unbind auto-closing
    if ( this.options.mode == "popover" ) {
      $("body").unbind("click");
    }
  }
}));

$(function() {
  // all init
  Swish.ui.init();
});

function showItemOptions(itemid,listid) {
	if ( listid ) {
		Swish.utils.setCookieWithTime("forcelist",listid,(10*60*1000));
	}
	$("#gpop").load("/axj/showItemOptions.html?itemid=" + itemid, finishPop("maindiv","middle",640));
}

function showStores(itemid) {
	$("#gpop").load("/axj/showStores.html?itemid=" + itemid, finishPop("maindiv","middle",640));
}

function editItemName(itemid,anchor,orient) {
	$("#gpop").load("/axj/editItemName.html?itemid=" + itemid, finishPop(anchor,orient,400));
}

function showPriceAlert(itemid,userid,anchor,orient) {
	$("#gpop").load("/axj/showPriceAlert.html?itemid=" + itemid + "&userid=" + userid, finishPop(anchor,orient,410));
}

function showPrices(listid,itemid,anchor,orient) {
	$("#gpop").load("/axj/showPrices.html?listid=" + listid + "&itemid=" + itemid, finishPop(anchor,orient,610));
}

function switchToPopupHelp(helppage) {
	$("#gpop").load("/pinfo/" + helppage, dummy);
}

function switchToStores(itemid) {
	$("#gpop").load("/axj/showStores.html?itemid=" + itemid, dummy);
}

function switchToItemOptions(itemid,storeid) {
	$("#gpop").load("/axj/showItemOptions.html?itemid=" + itemid + "&storeid=" + storeid, dummy);
}

function switchToItemStores(itemid) {
	$("#gpop").load("/axj/showItemStores.html?itemid=" + itemid, dummy);
}

function squareImage(selector,size) {
	$(selector).each(function() {
		var h = $(this).height();
		if ( h > size ) { $(this).attr("height",size); }
		var w = $(this).width();
		if ( w > size ) { $(this).attr("height","").attr("width",size); }
	});
}

function afterPriceAlert() {
	$("#listname").html(name);
	$("#wholeform").html("<br/><br/><img src=\"/images/checkmark.png\" style=\"margin-top: 0px;\" height=\"22\" />&nbsp;&nbsp;<h2 style=\"display:inline;\">Success! Your wishlist is renamed.</h2><br /><br/>");
	setTimeout("hideAll();", 2000);	
}

function dummy() {
  Swish.ui.init();
}

