/* eslint-env browser, jquery */
/* global moment, config, vega, vegam, vegaTooltip, vegaLite, g1 */
/* exported updateParams, vegamDraw, unitDraw, filterTime, filterSelect, drawFilters, drawViz, updateView */

function updateParams(params, keeponly, remove) {
  var query = g1.url.parse(params);
  keeponly = keeponly || [];
  remove = remove || [];
  if (keeponly.length) {
    var to_remove = Object.keys(query.searchKey).filter(function (i) {
      // remove filter-like characters from end
      var ci = i.replace(/(>~|<~|!~|>|<|~|\*|!)$/, "");
      return keeponly.indexOf(ci) === -1;
    });
    remove.push.apply(remove, to_remove);
  }
  if (remove.length) {
    var update = {};
    remove.forEach(function (k) {
      update[k] = null;
    });
    query.update(update);
  }
  return query.toString();
}

function vegamDraw(s, on) {
  var $on = $(on);
  s.spec.width = $on.width();
  s.spec.height = 250;
  $on
    .css({ width: s.spec.width, height: s.spec.height })
    .addClass("overflow-auto vegam");
  // need vega spec to alter
  var removes = { "fit-x": "height", "fit-y": "width" };
  delete s.spec[removes[s.spec.autosize.type]];
  var vspec = vegaLite.compile(s.spec).spec;
  // remove tooltip for certain mark types
  vspec.marks.forEach(function (m) {
    if (["line", "area"].indexOf(m.type) > -1) {
      m.interactive = false;
    }
  });
  var view = new vega.View(vega.parse(vspec))
    .renderer("svg")
    .initialize(on)
    .hover()
    .run();
  view.addEventListener("click", function (event, item) {
    console.log("CLICK", event, item); // eslint-disable-line no-console
    if (typeof item !== "undefined" && "datum" in item) {
      console.log(item.datum); // eslint-disable-line no-console
    }
  });
  vegaTooltip.default(view, s.spec);
}

function unitDraw(o, on, formatter) {
  formatter = formatter || "";
  $(on).html(formatter(o[0].value));
}

function filterTime(start, end, on) {
  $(on).daterangepicker({
    startDate: new Date(start),
    endDate: new Date(end),
    locale: { format: "MMM D, YYYY" },
    ranges: {
      Today: [moment(), moment()],
      Yesterday: [moment().subtract(1, "days"), moment().subtract(1, "days")],
      "Last 7 Days": [moment().subtract(6, "days"), moment()],
      "Last 30 Days": [moment().subtract(29, "days"), moment()],
      "This Month": [moment().startOf("month"), moment().endOf("month")],
      "Last Month": [
        moment().subtract(1, "month").startOf("month"),
        moment().subtract(1, "month").endOf("month"),
      ],
    },
  });
}

function filterSelect(values, key, on) {
  var output = [];
  $.each(values, function (k, v) {
    output.push('<option value="' + v[key] + '">' + v[key] + "</option>");
  });
  var el = $(on);
  el.append(output.join(""));
  return el;
}

function drawFilters(params) {
  var query = g1.url.parse(params);
  var config_filter = config.filters;
  $.each(config_filter, function (k, spec) {
    if (spec.type == "select") {
      $.getJSON(spec.url).done(function (data) {
        var el = filterSelect(data, spec.column, spec.el);
        el.promise().done(function () {
          el.selectpicker({ style: "btn-info btn-sm" });
          if (query.searchKey[spec.column]) {
            setSelectFilter(el, query.searchKey[spec.column]);
          }
        });
      });
    } else if (spec.type == "daterange") {
      setDatefilter(spec, query);
    } else {
      console.warn("unsupported filter type"); // eslint-disable-line no-console
    }
  });
}

function setFilters(params) {
  var query = g1.url.parse(params);
  var config_filter = config.filters;
  $.each(config_filter, function (k, spec) {
    if (spec.type == "select") {
      if (query.searchKey[spec.column]) {
        setSelectFilter($(spec.el), query.searchKey[spec.column]);
      }
    } else if (spec.type == "daterange") {
      setDatefilter(spec, query);
    }
  });
}

function setDatefilter(spec, query) {
  var start = query.searchKey[spec.column + ">~"].substring(0, 10);
  var end = query.searchKey[spec.column + "<~"].substring(0, 10);
  start = start || moment().subtract(29, "days");
  end = end || moment();
  filterTime(start, end, spec.el);
}

function setSelectFilter(el, value) {
  el.selectpicker("val", value);
}

function viewOn(conf) {
  return $.ajax({
    url: conf.url,
    beforeSend: function () {
      this.conf = conf;
      var loading = conf.loading || '<i class="fa fa-spin fa-spinner"></i>';
      $(conf.on).html(loading);
    },
  });
}

function drawViz(params) {
  config.viewsConfig.forEach(function (spec) {
    viewOn({
      url: spec.url + updateParams(params, spec.keep || []),
      on: spec.on,
    })
      .done(function (data) {
        if (data.length == 0) {
          $(this.conf.on).html("[ No Data ]");
          return;
        }
        if (spec.type === "viz") {
          spec.viz[0]["data"] = data;
          var vm = vegam.vegam().fromjson(spec.viz);
          vegamDraw(vm, this.conf.on);
        } else if (spec.type === "kpi") {
          unitDraw(data, this.conf.on, spec.formatter);
        }
      })
      .fail(function (xhr) {
        console.error({ on: this.conf.on, error: xhr.statusText }); // eslint-disable-line no-console
        $(this.conf.on).html("[ error ]");
      });
  });
}

function updateView() {
  var params = g1.url.parse(location.search);
  setFilters(params);
  drawViz(params);
}
