/**
 * @provides javelin-behavior-comment-actions
 * @requires javelin-behavior
 *           javelin-stratcom
 *           javelin-workflow
 *           javelin-dom
 *           phuix-form-control-view
 *           phuix-icon-view
 *           javelin-behavior-phabricator-gesture
 */

JX.behavior('comment-actions', function(config) {
  var action_map = config.actions;

  var action_node = JX.$(config.actionID);
  var form_node = JX.$(config.formID);
  var input_node = JX.$(config.inputID);
  var place_node = JX.$(config.placeID);

  var rows = {};

  JX.DOM.listen(action_node, 'change', null, function() {
    var option = find_option(action_node.value);

    action_node.value = '+';

    if (option) {
      add_row(option);
    }
  });

  function find_option(key) {
    var options = action_node.options;
    var option;

    for (var ii = 0; ii < options.length; ii++) {
      option = options[ii];
      if (option.value == key) {
        return option;
      }
    }

    return null;
  }

  function add_row(option) {
    var action = action_map[option.value];
    if (!action) {
      return;
    }

    option.disabled = true;

    var icon = new JX.PHUIXIconView()
      .setIcon('fa-times-circle');
    var remove = JX.$N('a', {href: '#'}, icon.getNode());

    var control = new JX.PHUIXFormControl()
      .setLabel(action.label)
      .setError(remove)
      .setControl(action.type, action.spec);
    var node = control.getNode();

    JX.Stratcom.addSigil(node, 'touchable');

    var remove_action = function() {
      JX.DOM.remove(node);
      delete rows[action.key];
      option.disabled = false;
    };

    JX.DOM.listen(node, 'gesture.swipe.end', null, function(e) {
      var data = e.getData();

      if (data.direction != 'left') {
        // Didn't swipe left.
        return;
      }

      if (data.length <= (JX.Vector.getDim(node).x / 2)) {
        // Didn't swipe far enough.
        return;
      }

      remove_action();
    });

    rows[action.key] = control;

    JX.DOM.listen(remove, 'click', null, function(e) {
      e.kill();
      remove_action();
    });

    place_node.parentNode.insertBefore(node, place_node);

    return control;
  }

  function serialize_actions() {
    var data = [];

    for (var k in rows) {
      data.push({
        type: k,
        value: rows[k].getValue(),
        initialValue: action_map[k].initialValue || null
      });
    }

    return JX.JSON.stringify(data);
  }

  function get_data() {
    var data = JX.DOM.convertFormToDictionary(form_node);

    data.__preview__ = 1;
    data[input_node.name] = serialize_actions();

    return data;
  }

  function restore_draft_actions(drafts) {
    var draft;
    var option;
    var control;

    for (var ii = 0; ii < drafts.length; ii++) {
      draft = drafts[ii];

      option = find_option(draft);
      if (!option) {
        continue;
      }

      control = add_row(option);
    }
  }

  function onresponse(response) {
    if (JX.Device.getDevice() != 'desktop') {
      return;
    }

    var panel = JX.$(config.panelID);
    if (!response.xactions.length) {
      JX.DOM.hide(panel);
    } else {
      JX.DOM.setContent(
        JX.$(config.timelineID),
        [
          JX.$H(response.spacer),
          JX.$H(response.xactions.join(response.spacer))
        ]);
      JX.DOM.show(panel);
    }
  }

  JX.DOM.listen(form_node, ['submit', 'didSyntheticSubmit'], null, function() {
    input_node.value = serialize_actions();
  });

  if (config.showPreview) {
    var request = new JX.PhabricatorShapedRequest(
      config.actionURI,
      onresponse,
      get_data);

    var trigger = JX.bind(request, request.trigger);

    JX.DOM.listen(form_node, 'keydown', null, trigger);

    var always_trigger = function() {
      new JX.Request(config.actionURI, onresponse)
        .setData(get_data())
        .send();
    };

    JX.DOM.listen(form_node, 'shouldRefresh', null, always_trigger);
    request.start();

    var ondevicechange = function() {
      var panel = JX.$(config.panelID);
      if (JX.Device.getDevice() == 'desktop') {
        request.setRateLimit(500);
        always_trigger();
      } else {
        // On mobile, don't show live previews and only save drafts every
        // 10 seconds.
        request.setRateLimit(10000);
        JX.DOM.hide(panel);
      }
    };

    ondevicechange();

    JX.Stratcom.listen('phabricator-device-change', null, ondevicechange);
  }

  restore_draft_actions(config.drafts || []);

});
