/*jslint nomen: true, indent: 2, maxerr: 3, maxlen: 80*/
/*global window, RSVP, rJS, jIO*/
(function (window, document, RSVP, rJS, jIO) {
  "use strict";

  rJS(window)

  .declareMethod("preRenderDocument", function (parent_options) {
    var gadget = this;
    return gadget.jio_get(parent_options.jio_key)
    .push(function (parent_document) {
      return parent_document;
    });
  })

  .declareAcquiredMethod("getSetting", "getSetting")
  .declareAcquiredMethod("setSetting", "setSetting")
  .declareAcquiredMethod("jio_post", "jio_post")
  .declareAcquiredMethod("jio_get", "jio_get")
  .declareAcquiredMethod("jio_put", "jio_put")

  .ready(function () {
    var indices = [], db;

    db = jIO.createJIO({
      type: "query",
      sub_storage: {
        type: "indexeddb",
        database: "mynij"
      }
    });

    this.changeState({
      indices: indices,
      db: db
    });
  })

  .declareMethod('getAttachment', function () {
    var storage = this.state.db;
    return storage.getAttachment.apply(storage, arguments);
  })

  .declareMethod('putAttachment', function () {
    var storage = this.state.db;
    return storage.putAttachment.apply(storage, arguments);
  })

  .declareMethod('put', function () {
    var storage = this.state.db;
    return storage.put.apply(storage, arguments);
  })

  .declareMethod("add_page", function (page, index_name) {
    var gadget = this,
        indices,
        index;
    if (! gadget.state.indices[index_name]) {
      indices = gadget.state.indices;
      indices[index_name] = new FlexSearch(
        "memory",
        {stemmer : "en", filter : "en"}
      );
      gadget.changeState({
        indices : indices
      });
    }
    index = gadget.state.indices[index_name];
    return gadget.state.db.put(page.id, page)
    .push(function () {
      return index.add(page.id, page.title + "\n" + page.content);
    });
  })

  .declareMethod("get_page", function (id) {
    return this.state.db.get(id);
  })

  .declareMethod("pushIndexBlob", function (index_id, index_dict, info) {
    var gadget = this;
    return this.state.db.put(
      index_id,
      {type: "index", info: info}
    )
    .push(function () {
      return gadget.state.db.putAttachment(
        index_id, "ids",
        new Blob([index_dict.ids], {type : "application/json"}));
    })
    .push(function () {
      return gadget.state.db.putAttachment(
        index_id,
        "map",
        new Blob([index_dict.map], {type : "application/json"}));
    })
    .push(function () {
      return gadget.state.db.putAttachment(
        index_id,
        "ctx",
        new Blob([index_dict.ctx], {type : "application/json"}));
    });
  })
  .declareMethod("pushIndex", function (index_name) {
    var gadget = this;
    return gadget.getSetting('index_list', [])
      .push(function (index_list) {
        if (index_list.indexOf(index_name) === -1) {
          index_list.push(index_name);
          return gadget.setSetting('index_list', index_list);
        }
      });
  })
  .declareMethod("createIndexDoc", function (doc) {
    var gadget = this;
    return gadget.getSetting("portal_type")
      .push(function (portal_type) {
        doc.portal_type = portal_type;
        return gadget.getSetting("parent_portal_type");
      })
      .push(function (parent_portal_type) {
        doc.parent_portal_type = parent_portal_type;
        return gadget.jio_post(doc);
      });
  })

  .declareMethod("updateIndexDoc", function (key, update_dict) {
    var gadget = this;
    return gadget.jio_get(key)
      .push(function (doc) {
        var new_doc = Object.assign(doc, update_dict);
        return gadget.jio_put(key, new_doc);
      });
  })

  .declareMethod("save_index", function (index_name) {
    var gadget = this,
        serialized = this.state.indices[index_name].export_test(),
        index_id = "index-" + index_name;

    return gadget.pushIndexBlob(index_id,
                                serialized,
                                this.state.indices[index_name].info())
    .push(function () {
      console.log("Index saved : ");
      console.log(gadget.state.indices[index_name].info());
      return gadget.state.indices[index_name].info().items;
    })
    .push(undefined, function (my_error) {
      console.log(my_error);
    });
  })

  .declareMethod("get_index", function (index_name) {
    var gadget = this,
        ids,
        map,
        index_id = "index-" + index_name,
        new_index;

    new_index = FlexSearch.create("memory", {stemmer : "en", filter : "en"});
    return gadget.state.db.getAttachment(index_id, "ids", {"format": "text"})
    .push(function (result) {
      ids = result;
      return gadget.state.db.getAttachment(
        index_id,
        "map",
        {"format": "text"});
    })
    .push(function (result) {
      map = result;
      return gadget.state.db.getAttachment(index_id, "ctx", {"format": "text"});
    })
    .push(function (result) {
      new_index.import_test(ids, map, result);
      return new_index;
    })
    .push(undefined, function (my_error) {
      console.log(my_error);
    });
  })

  .declareMethod("get_available_indices", function () {
    var gadget = this,
        indices = [],
        query = 'type:index';
    return gadget.state.db.allDocs({"query" : query})
      .push(function (results) {
          results.data.rows.forEach((item, i) => {
              indices.push(item.id.split("index-")[1]);
          });
          return indices;
      });
  })

  // .declareMethod("get_index_info", function(){
  //     console.log("index in state : ");
  //     console.log(this.state.index.info());
  //     return this.get_index()
  //     .push(function(index){
  //         console.log("index in db :");
  //         console.log(index.info());
  //     });
  // })

  .declareMethod("search", function (search_key, index_name, limit) {
    var gadget = this,
    results = [];
    return gadget.get_index(index_name)
    .push(function (index) {
      if (!limit)
        limit = 1000;
      console.log(index.info());
      return index.search(search_key, limit);
    })
    .push(function (index_results) {
        return index_results;
    })
    .push(undefined, function (my_error) {
      console.log(my_error);
    });
  });
}(window, document, RSVP, rJS, jIO));