#!/usr/bin/env python
# -*- mode: python; encoding: utf-8 -*-
#
# Copyright 2010 Google Inc. All Rights Reserved.

"""This is the interface for managing the foreman."""


import json
import time

from grr.gui import renderers
from grr.gui.plugins import flow_management
from grr.lib import aff4
from grr.lib import flow
from grr.lib import rdfvalue


class ManageForeman(renderers.UserLabelCheckMixin, renderers.Splitter2Way):
  """Manages class based flow creation."""
  description = "Automated flows"
  behaviours = frozenset(["General"])
  AUTHORIZED_LABELS = ["admin"]
  top_renderer = "ReadOnlyForemanRuleTable"
  bottom_renderer = "EmptyRenderer"


class RegexRuleArray(renderers.RDFValueArrayRenderer):
  """Nicely render all the rules."""
  proxy_field = "regex_rules"


class ActionRuleArray(renderers.RDFValueArrayRenderer):
  """Nicely render all the actions for a rule."""
  proxy_field = "actions"

  translator = dict(argv=renderers.RDFProtoRenderer.ProtoDict)


class ReadOnlyForemanRuleTable(renderers.TableRenderer):
  """Show all the foreman rules."""

  def __init__(self, **kwargs):
    super(ReadOnlyForemanRuleTable, self).__init__(**kwargs)
    self.AddColumn(renderers.RDFValueColumn("Created"))
    self.AddColumn(renderers.RDFValueColumn("Expires"))
    self.AddColumn(renderers.RDFValueColumn("Description"))
    self.AddColumn(renderers.RDFValueColumn(
        "Rules", renderer=RegexRuleArray, width="100%"))

  def RenderAjax(self, request, response):
    """Renders the table."""
    fd = aff4.FACTORY.Open("aff4:/foreman", token=request.token)
    rules = fd.Get(fd.Schema.RULES, [])
    for rule in rules:
      self.AddRow(Created=rule.created,
                  Expires=rule.expires,
                  Description=rule.description,
                  Rules=rule,
                  Actions=rule)

    # Call our baseclass to actually do the rendering
    return super(ReadOnlyForemanRuleTable, self).RenderAjax(request, response)


class ForemanRuleTable(ReadOnlyForemanRuleTable, renderers.UserLabelCheckMixin):
  """Show all existing rules and allow for editing."""

  selection_publish_queue = "rule_select"

  AUTHORIZED_LABELS = ["admin"]

  layout_template = renderers.TableRenderer.layout_template + """
<script>
  //Receive the selection event and emit the rule creation time.
  grr.subscribe("select_table_{{ id|escapejs }}", function(node) {
    if (node) {
      var row_id = node.attr("row_id");
      grr.layout("AddForemanRule", "main_bottomPane", {rule_id: row_id});
      grr.publish("{{ this.selection_publish_queue|escapejs }}", row_id);
    };
  }, '{{ unique|escapejs }}');

</script>
"""

  def Layout(self, request, response):
    # First render the toolbar.
    ForemanToolbar().Layout(request, response)
    return super(ForemanRuleTable, self).Layout(request, response)


class ForemanToolbar(renderers.TemplateRenderer):
  """Renders the toolbar."""

  layout_template = renderers.Template("""
<button id="add_rule" title="Add a new rule." class="grr-button">
  Add Rule
</button>
<script>
  $("#add_rule").button().click(function () {
     grr.layout("AddForemanRule", "main_bottomPane");
  });
</script>
""")


class AddForemanRule(flow_management.FlowInformation):
  """Present a form to add a new rule."""

  layout_template = renderers.Template("".join((
      # This is the toolbar for manipulating the rule
      """
<div class="toolbar">
<button title="Add Condition" id="AddCondition" class="grr-button">
Add Condition
</button>

<button title="Add Action" id="AddAction" class="grr-button">
Add Action
</button>

<button title="Delete Rule" id="DeleteRule" class="grr-button">
Delete Rule
</button>
</div>
""",

      # Scripts to add new rules based on jquery templates
      """<div id="form_{{unique|escapejs}}" class="FormBody">
<script id="addRuleTemplate" type="text/x-jquery-tmpl">
  <tbody id="condition_row_${rule_number}">
    <tr><td colspan=3 class="grr_aff4_type_header"><b>Regex Condition</b>
      <a href="#" title="Remove condition"
         onclick="$('#condition_row_${rule_number}').html('');">
         <img src="/static/images/window-close.png" class="toolbar_icon">
      </a>
    </td></tr>
    <tr><td class="proto_key">Path in client</td><td class="proto_value">
      <input name="path_${rule_number}" type=text size=40 /></td></tr>

    <tr><td class="proto_key">Attribute</td><td class="proto_value">
      <select name="attribute_name_${rule_number}" type=text size=1>
        {% for option in this.attributes %}
          <option>{{option|escape}}</option>
        {% endfor %}
      </select>
    </td> </tr>
    <tr><td class="proto_key">Regex</td><td class="proto_value">
      <input name="attribute_regex_${rule_number}" type=text size=40 /></td>
    </tr>
  </tbody>
</script>""",

      # Scripts to add a new action based on jquery templates
      """<script id="addActionTemplate" type="text/x-jquery-tmpl">
 <tbody id="action_row_${rule_number}">
   <tr><td colspan=3 class="grr_aff4_type_header"><b>Action</b>
     <a href="#" title="Remove Action"
        onclick="$('#action_row_${rule_number}').html('');">
       <img src="/static/images/window-close.png" class="toolbar_icon">
     </a>
   </td></tr>
   <tr><td class="proto_key">Flow Name</td><td class="proto_value">
     <select name="flow_name_${rule_number}" type=text size=1
       onchange="grr.layout('RenderFlowForm', 'flow_form_${rule_number}',
                            {rule_id: ${rule_id}, flow: this.value,
                             action_id: ${rule_number}});">
         <option>Select a Flow</option>
       {% for option in this.flows %}
         <option>{{option|escape}}</option>
       {% endfor %}
     </select>
   </td></tr>
 </tbody>
 <tbody id="flow_form_${rule_number}"></tbody>
</script>""",

      # Rendering the actual form
      """<h1>Add a new automated rule.</h1>
<form id="form">
<input type="hidden" name="rule_id" />
<table id="ForemanFormBody" class="form_table">
<tbody>
<tr><td class="proto_key">Created On</td>
<td class="proto_value">
<input type=text name="created_text" disabled="disabled"/></td>
</tr>

<tr><td class="proto_key">Expires On</td><td class="proto_value">
<input type=text size=20 name="expires_text"/>
</td></tr>

<tr><td class="proto_key">Description</td><td class="proto_value">
<input type=text size=20 name="description"/></td></tr>

</tbody>
</table>
<table id="ForemanFormRuleBody" class="form_table"></table>
<table id="ForemanFormActionBody" class="form_table"></table>

<input id="submit" type="submit" value="Launch"/>
</form>
</div>""",

      # Initialize the form - adds actions to toolbar items
      """<script>
  var defaults = {{ this.defaults|safe }};

  // Submit button
  $('#submit').button().click(function () {
    return grr.submit('AddForemanRuleAction', 'form',
      'form_{{unique|escapejs}}', false, grr.layout);
  });

  $('#AddAction').button().click(function () {
    grr.foreman.add_action({rule_id: defaults.rule_id});
  });

  $('#AddCondition').button().click(function () {
    grr.foreman.add_condition({rule_id: defaults.rule_id});
  });

  $('#DeleteRule').button().click(function () {
      grr.layout('DeleteRule', 'form_{{unique|escapejs}}',
      {rule_id: defaults.rule_id});
  });

  $("[name='expires_text']").datepicker(
    {dateFormat: 'yy-mm-dd', numberOfMonths: 3});

  // Place the first condition
  grr.foreman.regex_rules = 0;
  for (i=0; i<defaults.rule_count; i++) {
    grr.foreman.add_condition(defaults);
  };

  grr.foreman.action_rules = 0;