/*global window, rJS, loopEventListener */
/*jslint nomen: true, indent: 2, maxerr: 3*/
(function (window, rJS, loopEventListener, JSZip, FileSaver) {
  "use strict";

  function getExtension(url) {
    var extension = url.split('.').pop();
    if (extension.endsWith('/')) {
      return ".html";
    }
    return "." + extension;
  }  

  function createJio(gadget, jio_config) {
    var jio_gadget;
    return gadget.getDeclaredGadget("jio_gadget")
      .push(function (jio_g) {
        jio_gadget = jio_g;
        if (jio_config === undefined)
          jio_config = {type: "indexeddb", database: "cribjs"};
        return jio_gadget.createJio(jio_config);
    });
  }

  function createDAVJio(gadget, event) {
    return createJio(gadget, {
      type:"dav",
      url: gadget.props.element.querySelector('.form-use-jio-dav .url').value,
      basic_login: btoa(gadget.props.element.querySelector(".form-use-jio-dav .credential").value)
    });
  }  

  function saveContentToJIO(gadget, event) {
    var path_to_save, path_to_save_length, application_id, crib_sw_gadget,
      jio_gadget, url_list = [], saved_number = 0;
    path_to_save = gadget.props.element.querySelector('form.crib-save-to-jio .save-path').value
    application_id = gadget.props.element.querySelector('form.crib-save-to-jio .save-id').value
    path_to_save_length = path_to_save.length;
    return new RSVP.Queue()
    .push(function () {
      return RSVP.all([
        gadget.getDeclaredGadget('jio_gadget')]);
    })
    .push(function (gadget_list) {
      jio_gadget = gadget_list[0];
      return gadget.crib_sw_allDocs({cached_only: true});
    })
    .push(function(data) {
      url_list = data.urls;
      // This is buggy, it fails if the document already exists with dav storage
      return RSVP.all(
        [jio_gadget.put("/" + application_id + ".attachment/", {
                 // url: path_to_save
                  }),
         jio_gadget.putAttachment("/", application_id, new Blob([JSON.stringify({url: path_to_save})],{type: "application/json"}))  
      ]);      
    })
    .push(function() {
      var promise_list = [],
        i, i_len, url;
      for (i = 0, i_len = url_list.length; i < i_len; i += 1) {
        url = new String(url_list[i]);
        if (url.indexOf(path_to_save) === 0) {
          saved_number += 1;
          promise_list.push(gadget.crib_sw_get(url));
        };
      };
      return RSVP.all(promise_list);
    })
    .push(function(response_list) {
      var promise_list = [],
        i, i_len, url, response, extension;
      for (i = 0, i_len = response_list.length; i < i_len; i += 1) {
        response = response_list[i];
        url = response.responseURL.substr(path_to_save_length)
        extension = getExtension(url)
        promise_list.push(
          jio_gadget.putAttachment("/" + application_id + ".attachment/", btoa(url) + extension,
            // XXX Not sure it would work with images
            new Blob([response.responseText], {type : response.responseType})
          )
        );
      };
      return RSVP.all(promise_list)
    })
    .push(function() {
      gadget.props.element.querySelector(".crib-save-to-jio-status").textContent = "Saved " + saved_number + " files at "+ Date ()
    })
  }


  function loadContentFromJIO(gadget, event) {
    var path_to_load, path_to_load_length, application_id, crib_sw_gadget,
      jio_gadget, url_list = [];
    path_to_load = gadget.props.element.querySelector('form.crib-load-from-jio .load-path').value
    application_id = gadget.props.element.querySelector('form.crib-load-from-jio .load-id').value
    path_to_load_length = path_to_load.length;
    return new RSVP.Queue()
    .push(function () {
      return RSVP.all([
        gadget.getDeclaredGadget('jio_gadget')]);
    })
    .push(function (gadget_list) {
      jio_gadget = gadget_list[0];
      return jio_gadget.allAttachments("/" + application_id + ".attachment/");
    })
      .push(function(response) {
        var promise_list = [],
          key, extension;
        for (key in response) {
          if (response.hasOwnProperty(key)) {
            extension = getExtension(key);
            url_list.push(atob(key.substr(0, key.length - extension.length)))
            promise_list.push(jio_gadget.getAttachment("/" + application_id + ".attachment/", key));
          }
        };
        return RSVP.all(promise_list)
      })
      .push(function(response_list) {
        var promise_list = [],
          i, i_len, url, index, response, location, location_len;
        location = document.location.origin;
        location_len = location.length
        for (i = 0, i_len = response_list.length; i < i_len; i += 1) {
          url = url_list[i]
          index = url.indexOf(location);
          if (index != -1)
            url = url.substr(index + location_len);
          promise_list.push( 
            gadget.crib_sw_put(path_to_load + url, {blob: response_list[i]})
          )
        }
      })
      .push(function() {
        gadget.props.element.querySelector(".crib-load-from-jio-status").textContent = "Loaded " + url_list.length + " files at "+ Date ()
      });
  }

  // Zip Methods
  function saveContentToZIP(gadget, event) {
    var path_to_save, path_to_save_length, application_id, crib_sw_gadget,
      jio_gadget, url_list = [], saved_number = 0, zip;
    path_to_save = gadget.props.element.querySelector('form.crib-save-to-zip .save-zip-path').value
    application_id = gadget.props.element.querySelector('form.crib-save-to-zip .save-zip-id').value
    path_to_save_length = path_to_save.length;
    return new RSVP.Queue()
    .push(function () {
      return RSVP.all([
        gadget.getDeclaredGadget('jio_gadget')]);
    })
    .push(function (gadget_list) {
      jio_gadget = gadget_list[0];
      return gadget.crib_sw_allDocs({cached_only: true});
    })
    .push(function(data) {
      var promise_list = [],
        i, i_len, url;
      if (Array.isArray(data.urls)) {
        url_list = data.urls;
      } else {
      	url_list = Object.keys(data.urls);
      }
      for (i = 0, i_len = url_list.length; i < i_len; i += 1) {
        url = new String(url_list[i]);
        if (url.indexOf(path_to_save) === 0) {
          saved_number += 1;
          promise_list.push(gadget.crib_sw_get(url));
        };
      };
      return RSVP.all(promise_list);
    })
    .push(function(response_list) {
      var promise_list = [],
        i, i_len, url, response, extension, zip;
      zip = new JSZip();
      for (i = 0, i_len = response_list.length; i < i_len; i += 1) {
        response = response_list[i];
        url = url_list[i].substr(path_to_save_length)
        if ( url.endsWith("/") ) {
          url = url + "index.html";
        }
        zip.file(url, response)
      };
      return zip.generateAsync({type:"blob"});
    })
    .push(function(content) {
      return saveAs(content, application_id)
    })
    .push(function() {
      gadget.props.element.querySelector(".crib-save-to-zip-status").textContent = "Saved " + saved_number + " files at "+ Date ()
    })
    .push(console.log, console.log)
  }


  function loadContentFromZIP(gadget, event) {
    var path_to_load, path_to_load_length, file_list, crib_sw_gadget,
      jio_gadget, url_list = [], file, url_number = 0;
    path_to_load = gadget.props.element.querySelector('form.crib-load-from-zip .load-zip-path').value
    file_list = gadget.props.element.querySelector('form.crib-load-from-zip .load-zip-file').files
    if (file_list.length === 0) {
      gadget.props.element.querySelector(".crib-load-from-zip-status").textContent = "Please put a Zip at "+ Date ()
      return 
    }
    path_to_load_length = path_to_load.length;
    file = file_list[0]
    return new RSVP.Queue()
    .push(function () {
      return JSZip.loadAsync(file);
    })
    .push(function (zip) {
      var promise_list = [];
      zip.forEach(function (relativePath, zipEntry) {
        var end_url;
        url_number += 1;
        if ( zipEntry.dir ) {
          return
        }
        if (!relativePath.startsWith("/") && !path_to_load.endsWith("/")) {
          end_url = path_to_load + "/" + relativePath 
        } else if (relativePath.startsWith("/") && path_to_load.endsWith("/")) {
          end_url = path_to_load + relativePath.substring(1);
        } else {
          end_url = path_to_load + relativePath 
        }
        promise_list.push(
          new RSVP.Queue().
            push(function () {
              return zipEntry.async('blob');
            })
            .push(function (result) {
              if ( end_url.endsWith(".js") ) {
                // This is a ugly hack as mimetype needs to be correct for JS
                result = result.slice(0, result.size, "application/javascript")
              } else if ( end_url.endsWith(".html") ) {
                // This is a ugly hack as mimetype needs to be correct for JS
                result = result.slice(0, result.size, "text/html")
              } else if ( end_url.endsWith(".css") ) {
                // This is a ugly hack as mimetype needs to be correct for JS
                result = result.slice(0, result.size, "text/css")
              } 
              return gadget.crib_sw_put(end_url, {blob: result})
            })
        )
      })
      return RSVP.all(promise_list)
    })
    .push(function() {
      gadget.props.element.querySelector(".crib-load-from-zip-status").textContent = "Loaded " + url_number + " files at "+ Date ()
    })
    .push(console.log, console.log)
  }  
  rJS(window)
    .ready(function (g) {
      g.props = {};
      return g.getElement()
        .push(function (element) {
          g.props.element = element;
          g.props.start_deferred = RSVP.defer();
         });
    })
    .declareAcquiredMethod("crib_sw_allDocs", "crib_sw_allDocs")
    .declareAcquiredMethod("crib_sw_get", "crib_sw_get")
    .declareAcquiredMethod("crib_sw_put", "crib_sw_put")
    .declareAcquiredMethod("getUrlFor", "getUrlFor")
    .declareMethod('render', function (options) {
      var gadget = this;
      if (options === undefined)
        options = {};
      gadget.props.options = options;
      gadget.props.element.querySelector('form.crib-save-to-jio .save-path').value = document.location.origin;
      gadget.props.element.querySelector('form.crib-load-from-jio .load-path').value = document.location.origin;
      gadget.props.element.querySelector('form.crib-save-to-zip .save-zip-path').value = document.location.origin;
      return new RSVP.Queue()
        .push(function () {
          return gadget.props.start_deferred.resolve();
        })  
    })
    .declareService(function () {
      var gadget = this;
      return new RSVP.Queue()
        .push(function () {
          return gadget.props.start_deferred.promise;
        })
        .push(function () {
          var promise_list = [];
          // promise to save content to jIO
          promise_list.push(loopEventListener(
            gadget.props.element.querySelector(".crib-save-to-jio"),
            'submit',
            false,
            function (event) {saveContentToJIO(gadget, event)}
          ));
          // promise to load content from jIO
          promise_list.push(loopEventListener(
            gadget.props.element.querySelector(".crib-load-from-jio"),
            'submit',
            false,
            function (event) {loadContentFromJIO(gadget, event)}
          ));
          // promise to use dav storage for jIO
          promise_list.push(loopEventListener(
            gadget.props.element.querySelector(".form-use-jio-dav"),
            'submit',
            false,
            function (event) {createDAVJio(gadget, event)}
          ));
          // promise to use local storage for jIO
          promise_list.push(loopEventListener(
            gadget.props.element.querySelector(".form-use-jio-local"),
            'submit',
            false,
            function (event) {createJio(gadget, {type: "indexeddb", database: "cribjs"})}
          ));
          // promise to save content to ZIP
          promise_list.push(loopEventListener(
            gadget.props.element.querySelector(".crib-save-to-zip"),
            'submit',
            false,
            function (event) {saveContentToZIP(gadget, event)}
          ));
          // promise to load content from ZIP
          promise_list.push(loopEventListener(
            gadget.props.element.querySelector(".crib-load-from-zip"),
            'submit',
            false,
            function (event) {loadContentFromZIP(gadget, event)}
          ));
          return RSVP.all(promise_list);
        });
    })  
}(window, rJS, loopEventListener, JSZip, FileSaver));