var regexp = {};

regexp.extract = function(re, s) {
  var m = s.match(re);
  if (m) {
    m.shift();
    return m
  } else {
    return []
  }
}

regexp.match = function(re, s) {
  return s.match(re)
}

regexp.replace = function(re, template, s) {
  return s.replace(re, template)
}

function chain(promise) {
  var dfd = new jQuery.Deferred();
  var fs = Array.prototype.slice.call(arguments, 1);
  var b = function(a) {
    var f = fs.shift();
    return $.when((f(a))).done((fs.length == 0) ? (function(a) {
      return dfd.resolve(a)
    }) : b)
  };
  promise.done(b);
  return dfd.promise()
}

function fold(f, a, x) {
  if (!Array.prototype.reduce) {
    for (var i = 0; i < x.length; i++) {a = f.call(null, a, x[i])};
    return a
  } else {
    return array(x).reduce(f, a)
  }
}

function keys(a) {
  if (Object.keys) {
    return Object.keys(a)
  } else {
    var x = [];
    for (var p in a) if (Object.prototype.hasOwnProperty.call(a, p)) x.push(p);;
    return x
  }
}

function array(a) {
  if (a != null) {
    if (!a.push) {
      return [a]
    } else {
      return a
    }
  } else {
    return []
  }
}

function map(f, x) {
  if (!Array.prototype.map) {
    var a = new Array();
    x = array(x);
    for (var i = 0; i < x.length; i++) {a.push(f.call(null, x[i]))};
    return a
  } else {
    return array(x).map(f)
  }
}

function map_promise(f, x, a, b) {
  if (x) {
    return $.when.apply($, map((function(x) {
      return f(x, a)
    }), x)).pipe(function(u) {
      return b
    })
  } else {
    return $.when(b)
  }
}

function string(a) {
  if (a == null) {
    return ""
  } else {
    return a
  }
}

website = {
  "change_uri" : function(uri, p) {
    var m = regexp.extract(/^([^?]+)([?](.*))?$/, uri);
    var qs = fold(function(a, b) {
      var x = b.split("=", 2);
      if (!p[x[0]]) {
        return (a ? (string(a) + "&") : "?") + string(b)
      } else {
        return a
      }
    }, null, m[2] ? m[2].split("&") : null);
    return string(m)[0] + string(qs) + (qs ? "&" : "?") + string(map((function(a) {
      return string(a) + "=" + string(p)[string(a)]
    }), keys(p))).join("&")
  }, 
  "each" : function(a, f) {
    if (a) {
      if ((typeof(a) == "object") && a.push) {
        for (var i = 0; i < a.length; i++) {f(a[i])}
      } else {
        return f(a)
      }
    } else {
      return null
    }
  }, 
  "edit_text" : function(a) {
    var restore = function(change) {
      var v = ui.val();
      return a.empty().text(change ? v : value)
    };
    var ui = $("<input type=\"text\"/>");
    var value = a.text();
    ui.val(value);
    a.empty().append(ui);
    ui.select();
    ui.blur(function(event) {
      event.preventDefault();
      restore(true);
      return false
    });
    ui.keyup(function(event) {
      if (event.which == 13) {
        return restore(true)
      } else {
        if (event.which == 27) {
          return restore(false)
        } else {
          return true
        }
      }
    });
    return a
  }, 
  "load_script" : function(uri, vn) {
    var promise = website.script[uri];
    if (!promise) {
      var deferred = new jQuery.Deferred();
      promise = deferred.promise();
      website.script[uri] = promise;
      var node = document.createElement("script");
      node.setAttribute("type", "text/javascript");
      node.setAttribute("src", uri);
      if ($.browser.msie) {
        node.onreadystatechange = function(u) {
          if (node.readyState == "complete") {
            return deferred.resolve()
          }
        }
      } else {
        node.onload = function(u) {
          return deferred.resolve()
        }
      };
      $("head")[0].appendChild(node)
    };
    return promise.done(function(u) {
      var m = uri.match(/^\/[0-9]+\/view\/([^.]+)\.js/);
      if (m && website.script[m[1]]) {
        var name = null;
        if (vn) {
          name = vn[1]
        } else {
          name = m[1]
        };
        var view = null;
        if (vn) {
          view = vn[0]
        } else {
          view = null
        };
        if (!view || !view.hasClass(name)) {
          return $((".view." + string(m)[1]), view).each(function(i, x) {
            return website.script[m[1]]($(x))
          })
        } else {
          return website.script[m[1]](view)
        }
      }
    })
  }, 
  "load_stylesheet" : function(uri, view) {
    var promise = website.style[uri];
    if (!promise) {
      var deferred = new jQuery.Deferred();
      var promise = deferred.promise();
      website.style[uri] = promise;
      var node = document.createElement("link");
      node.setAttribute("rel", "stylesheet");
      node.setAttribute("type", "text/css");
      node.setAttribute("href", uri);
      $("head")[0].appendChild(node);
      window.setTimeout(function(u) {
        return deferred.resolve()
      }, 500);
      return promise
    } else {
      return promise
    }
  }, 
  "normalize" : function(a) {
    var m = a.match(/^http:\/\/[^\/]+(\/.*)$/);
    if (m) {
      return m[1]
    } else {
      return a
    }
  }, 
  "query_string" : function(uri) {
    var m = uri.match(/\?(.*)$/);
    if (m) {
      return fold(function(a, b) {
        var x = b.split("=", 2);
        a[x[0]] = x[1] ? (regexp.match(/^\s*\d+([.]\d+)?\s*$/, x[1]) ? parseFloat(x[1]) : x[1]) : true;
        return a
      }, {
        
      }, m[1].split("&"))
    } else {
      return {
        
      }
    }
  }, 
  "request" : function(uri, method, headers, data) {
    headers = headers || {};
    method = method || "GET";
    if (website["static"]) {
      return website.iframe[0].contentWindow.website.request(uri, method, headers, data)
    } else {
      console.log(uri);
      if (data) {
        return $.ajax({
          "cache" : false, 
          "contentType" : "application/json", 
          "data" : JSON.stringify(data), 
          "processData" : false, 
          "type" : method, 
          "url" : uri
        })
      } else {
        return $.ajax({
          "cache" : false, 
          "type" : method, 
          "url" : uri
        })
      }
    }
  }, 
  "scarce" : function(a, side) {
    var busy = true;
    var delay = null;
    var hide = null;
    var inside = false;
    var options = {
      "hide" : {
        
      }, 
      "show" : {
        
      }
    };
    var show = null;
    var shown = true;
    options.hide[side] = "-" + string(a).css((((side == "top") || (side == "bottom")) ? "height" : "width"));
    options.show[side] = 0;
    delay = function(u) {
      return window.setTimeout(function(u) {
        busy = false;
        if (shown != inside) {
          if (shown) {
            return hide(null)
          } else {
            return show(null)
          }
        }
      }, 1000)
    };
    show = function(u) {
      busy = true;
      shown = true;
      a.removeClass("hidden");
      return a.animate(options.show, "slow", delay)
    };
    hide = function(u) {
      busy = true;
      shown = false;
      a.addClass("hidden");
      return a.animate(options.hide, "slow", delay)
    };
    $("button", a).click(function(event) {
      event.preventDefault();
      if (!busy) {
        inside = !inside;
        if (shown) {
          hide(null)
        } else {
          show(null)
        }
      };
      return false
    });
    a.mouseenter(function(event) {
      event.preventDefault();
      inside = true;
      if (!busy) {
        show(null)
      };
      return false
    });
    a.mouseleave(function(event) {
      event.preventDefault();
      inside = false;
      if (!busy) {
        delay(null)
      };
      return false
    });
    delay(null);
    return a
  }, 
  "show" : function(view, uri, method, headers, data) {
    var uri = website.substitute(uri);
    var widget = view.closest(".widget");
    view.data("uri", uri);
    view.data("qs", website.query_string(uri));
    widget.trigger("in:" + "loading", [view]);
    return chain(website.request(uri, method, headers, data), function(data) {
      return map_promise(website.load_stylesheet, data.style, view, data)
    }, function(data) {
      view.empty().scrollTop(0).attr("class", (string(view).attr("class").replace(/^((.*)view\s)?.*$/, "$2view ") + string(data)["class"] + (view.hasClass("active") ? " active" : ""))).append(data.xml).data(data.data);
      return data
    }, function(data) {
      return map_promise(website.load_script, data.script, [view, data.name], data)
    }, function(data) {
      widget.trigger("in:" + "loaded", [view]);
      return data
    })
  }, 
  "substitute" : function(s) {
    var m = regexp.extract(/^\/([^?]*)(.*[?&])([^=]+)={([^}]+)}(.*)$/, s);
    if (m[0]) {
      return website.substitute("/" + string(m)[0] + string(m)[1] + string(m)[2] + "=" + string(localStorage)[((m[3] == ".") ? (string(m)[0].replace(/\//g, ".") + "." + string(m)[2]) : string(m)[3])] + string(m)[4])
    } else {
      return s
    }
  }, 
  "swipe" : function(a) {
    a.bind("touchstart", function(event) {
      website.touch = [event.targetTouches[0].pageX, event.targetTouches[0].pageY, a.scrollTop()];
      return null
    });
    a.bind("touchend", function(event) {
      website.touch = null;
      return website
    });
    return a.bind("touchmove", function(event) {
      event.preventDefault();
      var offset = website.touch[1] - event.targetTouches[0].pageY;
      a.scrollTop(website.touch[2] + offset);
      return false
    })
  }
}

$(function(){
  document.domain = window.location.host.replace(/^(www|app)\./, "");
  if (!window.console) {
    window.console = {
      "log" : function(u) {
        return null
      }
    }
  };
  website.deploy = $("head > script[src$=\"/lx.js\"]").attr("src").match(/^(https?:\/\/[^\/]+)?\/(\d+)\/script\/lx.js$/)[2];
  website.mobile = /mobile/i.test(navigator.userAgent);
  if (website.mobile) {
    $.event.props.push("touches", "targetTouches", "changedTouches")
  };
  if (website["static"] = !window.location.host.match(/^app\./)) {
    website.app = window.location.host.replace(/^www\./, "app.");
    var dfd = new jQuery.Deferred();
    website.iframe = $(("<iframe id=\"lx-request\" src=\"" + ("http://" + string(website).app + "/" + string(website).deploy + "/rest.html") + "\" style=\"visibility:hidden\"></iframe>")).appendTo("body");
    website.iframe.load(function(u) {
      return dfd.resolve(null)
    });
    website.ready = dfd.promise()
  } else {
    website.app = window.location.host;
    website.ready = (new jQuery.Deferred()).resolve().promise()
  };
  website.style = {
    
  };
  website.script = {
    
  };
  $("link[rel=\"stylesheet\"]").each(function(i, a) {
    website.style[website.normalize(a.href)] = website.ready;
    return website.style
  });
  $("script[src]").each(function(i, a) {
    var uri = website.normalize(a.src);
    website.script[uri] = website.ready;
    return website.load_script(uri)
  })
})
