var feedback = function () {

  var defValues = {
    "feedback_form_textarea": {
      "question": "Do you have a question for us?",
      "idea": "Tell us your idea - we will think about it",
      "problem": "Tell us what you encountered - we will solve it."
    },
    "feedback_form_email": "please enter your email"
  };
  
  var containerId = 'feedback_container';
  var buttonSend = 'feedback_button_send';
  var buttons = [ 'feedback_button_send', 'feedback_button_cancel' ];
  
  var mode = "question"; //default
  var modes = ["question", "idea", "problem"];
  
  var tabPrefix = "feedback_tab_";
  var server = "/feedbackgw.php";
  
  var loaderAction = function () {
//     swapDOM("feedback_form",SPAN(null,"..lade.."));
  }
  
  var finishedAction = function (result) {
    if (result.error == "") {
      showElement("feedback_ok");
      
    } else {
      for (var i=0; i<buttons.length; i++) {
        getElement(buttons[i]).disabled=false;
      }
      for (var field in defValues) {
        getElement(field).disabled=false;
      }
      if (result.error == "invalid email") {
        errorAction("feedback_form_email","Please recheck your email or try again later.");
      } else {
        errorAction("","Unknown Error. Please try again later.");
      }
      //logFatal("[feedback] Server error: '"+repr(result.error)+"'");
    }
  }
  
  var finishedWithErrorAction = function (){
    for (var i=0; i<buttons.length; i++) {
      getElement(buttons[i]).disabled=false;
    }
    for (var field in defValues) {
      getElement(field).disabled=false;
    }
    errorAction("","We're sorry, there was a problem sending the report.");
  }
  
  var customSanityChecks = function () {
    return { "mess": "", "field": "" }; //no error
  }
  
  var errorAction = function (field,message) {
    //logDebug("showing message '"+message+"'");
    if (!isEmpty(field)) {
      addElementClass(field,"formborder_red");
    }
    replaceChildNodes("feedback_error",message);
    showElement("feedback_error");
    var d = callLater(1,partial(fade,"feedback_error"));
  }
  
  
  var defaultState;
  var signalHandlers = [];
  
  var servertoken;

  var checkvalue = function (objId) {
    //logDebug("[feedback] checking value for '"+repr(objId)+"'");
    var obj = getElement(objId);
    for (var val in defValues) {
      if (obj.id == val) {
        if ((typeof(defValues[val]) == "object" && obj.value == defValues[val][mode])
        || typeof(defValues[val]) == "string" && obj.value == defValues[val]) {
          //logDebug("[feedback] ok, clearing '"+repr(objId)+"'");
          obj.value = "";
        }
      }
    }
    removeElementClass(obj,"formborder_red");
  }
  
  var jumpto = function (newMode) {
    //log("[feedback] changing mode from '"+repr(mode)+"' to '"+repr(newMode)+"'");
    var oldmode = mode;
    mode = newMode;
    
    //logDebug("[feedback] changing active tab");
    removeElementClass(tabPrefix+oldmode,"feedback_tab_active");
    addElementClass(tabPrefix+oldmode,"feedback_tab_inactive");
    removeElementClass(tabPrefix+mode,"feedback_tab_inactive");
    addElementClass(tabPrefix+mode,"feedback_tab_active");
    
    //logDebug("[feedback] changing textarea value, if previously untouched");
    for (var field in defValues) {
      if (typeof(defValues[field]) == "object") {
        if (typeof(defValues[field][mode]) == "string" && (
          defValues[field][oldmode] == getElement(field).value ||
          getElement(field).value == ""
        )) {
          getElement(field).value = defValues[field][mode];
        }
      }
    }
  }
  
  var sanityChecks = function () {
    for (var val in defValues) {
      if ((typeof(defValues[val]) == "object" && getElement(val).value == defValues[val][mode])
      || typeof(defValues[val]) == "string" && getElement(val).value == defValues[val]
      || getElement(val).value == "") {
        return {"mess": "Please fill in all fields.", "field": val};
      }
    }
    return customSanityChecks();
  }
  
  var sendFeedback = function () {
    var res = sanityChecks();
    if (res.mess != "") {
      errorAction(res.field,res.mess);
      return false;
    }
    //log("[feedback] sending feedback now");
    for (var i=0; i<buttons.length; i++) {
      getElement(buttons[i]).disabled=true;
    }
    var message = {"feedback_form_token": servertoken,
      "feedback_form_subj": mode };
    for (var field in defValues) {
      message[field] = getElement(field).value;
      getElement(field).disabled=true;
    }
    loaderAction();
    //build query string
    var url = server+"?";
    var counter =0;
    for (var field in message) {
      if (counter != 0) {
        url = url+"&";
      }
      url = url+field+"="+urlEncode(message[field]);
      counter=counter+1;
    }
    //logDebug("ok, query string is '"+repr(url)+"', starting GET");
    var d = loadJSONDoc(url);
    d.addCallbacks(finishedAction, finishedWithErrorAction);
  }
  
  
  this.init = function (newToken) {
    servertoken = newToken;

    //logDebug("[feedback] initiating feedback");
    //log("[feedback] save default state from element with id '"+containerId+"'");
    defaultState = getElement(containerId).cloneNode(true)
    //log("[feedback] setting default values");
    for (var field in defValues) {
      if (typeof(defValues[field]) == "string") {
        //logDebug("[feedback] setting value of id '"+field+"' to default value '"+repr(defValues[field])+"'");
        getElement(field).value = defValues[field];
      } else if (typeof(defValues[field]) == "object") {
        //logDebug("[feedback] setting value of id '"+field+"' to default value '"+repr(defValues[field][mode])+"' for mode '"+repr(mode)+"'");
        getElement(field).value = defValues[field][mode];
      }
    }
    //log("[feedback] connecting signals to clear on focus");
    for (var field in defValues) {
      signalHandlers[signalHandlers.length] = connect(field,"onfocus", partial(checkvalue,field));
    }
    //log("[feedback] connecting signals for tabs");
    for (var i=0; i<modes.length; i++) {
      signalHandlers[signalHandlers.length] = connect(tabPrefix+modes[i],"onclick", partial(jumpto,modes[i]));
    }
    //log("[feedback] connecting signal for send-button")
    signalHandlers[signalHandlers.length] = connect(buttonSend,"onclick", sendFeedback );
    
    //log("[feedback] showing form");
    showElement(containerId);
  }
  
  this.destroy = function () {
    //log("[feedback] hiding form");
    hideElement(containerId);
    //log("[feedback] resetting state");
    swapDOM(containerId,defaultState);
    //log("[feedback] disconnecting signals");
    forEach(signalHandlers,function (ident) { disconnect(ident); });
    signalHandlers = [];
  }
  
}

var myFeedback = new feedback();

