/***********************************************************************
 ** Etresoft, Inc.
 ** Copyright (c) 2019. All rights reserved.
 **********************************************************************/

// Keep track of the current selection between reloads.
var focusedElement = null;
var startSelection = null;
var endSelection = null;

// Bindings.
var bindings = {};
var bindingInProgress = false;

// Update the view.
function ESWebViewLoad()
  {
  // Connect all labels to their associated controls.
  var labels = document.getElementsByTagName("LABEL");
  
  for(var i = 0; i < labels.length; ++i)
    (function ()
      {
      var label = labels[i];
      var control = label.parentNode.querySelector("input");
     
      // Propagate the click event.
      label.addEventListener(
        "click",
        function()
          {
          control.click();
          });

      // Simulate an active pseudoclass with a class.
      label.addEventListener(
        "mousedown",
        function()
          {
          control.className += " pactive";
          });

      // Simulate an active pseudoclass with a class.
      label.addEventListener(
        "mouseup",
        function()
          {
          if(control.className.endsWith(" pactive"))
            control.className =
              control.className.substring(
                0, control.className.length - 8);
          });
     
      // Simulate an active pseudoclass with a class.
      label.addEventListener(
        "mouseleave",
        function()
          {
          if(control.className.endsWith(" pactive"))
            control.className =
              control.className.substring(
                0, control.className.length - 8);
          });
      }());

  // Route click events to actions.
  var buttons = document.getElementsByTagName("BUTTON");
  
  for(var i = 0; i < buttons.length; ++i)
    (function ()
      {
      var button = buttons[i];
     
      var action = button.dataset.action;
     
      if(action != undefined)
        button.addEventListener(
          "click",
          function(event)
            {
            ESWebViewAction(event.target);
            });
      }());

  // Events common to all input elements.
  var controls = document.getElementsByTagName("INPUT");
  
  for(var i = 0; i < controls.length; ++i)
    (function ()
      {
      var control = controls[i];
     
      // Keep track of the focused text field.
      if(control.type == "text")
        {
        control.addEventListener(
          "focus",
          function(event)
            {
            focusedElement = event.target;
            });

        control.addEventListener(
          "blur",
          function(event)
            {
            focusedElement = null;
            });
        }
     
      // Bind a data value continuously.
      var binding = control.dataset["bind-continuousvalue"];
     
      if(binding != undefined)
        {
        control.addEventListener(
          "change",
          function(event)
            {
            ESWebViewValueChanged("bind-continuousvalue", event.target);
            });

        control.addEventListener(
          "input",
          function(event)
            {
            ESWebViewValueChanged("bind-continuousvalue", event.target);
            });
     
        if(typeof bindings[binding] === 'undefined')
          bindings[binding] = new Array();
     
        bindings[binding].push(
          {
          element: control,
          type: "bind-continuousvalue"
          });
        }
      else
        {
        // Bind a data value.
        binding = control.dataset["bind-value"];
     
        if(binding != undefined)
          {
          control.addEventListener(
            "change",
            function(event)
              {
              ESWebViewValueChanged("bind-value", event.target);
              });
     
          if(typeof bindings[binding] === 'undefined')
            bindings[binding] = new Array();
     
          bindings[binding].push(
            {
            element: control,
            type: "bind-value"
            });
          }
        }

      // Bind a disabled value.
      binding = control.dataset["bind-enabled"];
     
      if(binding != undefined)
        {
        if(typeof bindings[binding] === 'undefined')
          bindings[binding] = new Array();
     
        bindings[binding].push(
          {
          element: control,
          type: "bind-enabled"
          });
        }
      }());

  // Keep track of the current selection.
  document.addEventListener(
    "selectionchange",
    function()
      {
      if(focusedElement != null)
        {
        startSelection = focusedElement.selectionStart;
        endSelection = focusedElement.selectionEnd;
        }
      });
  }

// Activate the view by restoring focus and selection.
function ESWebViewActivate(parameters)
  {
  if(parameters.focusedElement != null)
    {
    focusedElement =
      document.getElementById(parameters.focusedElement);
    
    focusedElement.focus();
    
    startSelection = parameters.startSelection;
    endSelection = parameters.endSelection;
    
    if((startSelection != null) && (endSelection != null))
      focusedElement.setSelectionRange(startSelection, endSelection);
    }
    
  return JSON.stringify(parameters);
  }

// Save the focused element and selection on deactivate.
function ESWebViewDeactivate()
  {
  var result = "ok";
  
  if(focusedElement != null)
    if((startSelection != null) && (endSelection != null))
      result =
        {
        "focusedElement": focusedElement.id,
        "startSelection": startSelection,
        "endSelection": endSelection
        };
  
  return JSON.stringify(result);
  }

// Handle an action.
function ESWebViewAction(element)
  {
  var object =
    {
    id: element.id,
    class: element.className,
    tag: element.tagName,
    action: element.dataset.action,
    identifier: element.dataset.identifier,
    html: element.innerHTML
    };
    
  var message = JSON.stringify(object);

  if(window.webkit != undefined)
    window.webkit.messageHandlers.action.postMessage(message);
  else if(window.action != undefined)
    window.action.postMessage(message);
  else
    console.log("action " + message);
  }

// Handle a value changed event.
function ESWebViewValueChanged(binding, element)
  {
  if(bindingInProgress)
    return;
    
  var type = element.type;
  var value = element.value;
  
  if(type == "checkbox")
    value = element.checked;
  else if(type == "radio")
    value = element.checked;
  else if(type == "text")
    value = element.value;

  var object =
    {
    id: element.id,
    class: element.className,
    tag: element.tagName,
    value: value,
    html: element.innerHTML
    };
    
  object[binding] = element.dataset[binding];
  
  var message = JSON.stringify(object);

  if(window.webkit != undefined)
    window.webkit.messageHandlers.valueChanged.postMessage(message);
  else if(window.valueChanged != undefined)
    window.valueChanged.postMessage(message);
  else
    console.log("valueChanged " + message);
  }

// Bind values.
function ESWebViewBindValues()
  {
  var object =
    {
    bindings: bindings
    };

  var message = JSON.stringify(object);

  var result = null;

  if(window.webkit != undefined)
    result = window.webkit.messageHandlers.bindValues.postMessage(message);
  else if(window.bindValues != undefined)
    result = window.bindValues.postMessage(message);
  //else
  //  console.log("bindValues " + message);
  }

function ESWebViewBindValuesInitialize(values)
  {
  bindingInProgress = true;
  
  for(var key in values)
    if(values.hasOwnProperty(key))
      {
      var value = values[key];
      var elements = bindings[key];
      
      for(var i = 0; i < elements.length; ++i)
        {
        var binding = elements[i];
        
        if(binding.type == "bind-value")
          {
          if(binding.element.type == "checkbox")
            binding.element.checked = value;
          else if(binding.element.type == "radio")
            binding.element.checked = value;
          else if(binding.element.type == "text")
            binding.element.value = value;
          }
        else if(binding.type == "bind-continuousvalue")
          {
          if(binding.element.type == "text")
            binding.element.value = value;
          }
        else if(binding.type == "bind-enabled")
          {
          binding.element.disabled = !value;
          }
        }
      }
    
  bindingInProgress = false;
  }

// Value changed.
function ESWebViewBindValueChanged(key, value)
  {
  bindingInProgress = true;
  
  var elements = bindings[key];
  
  for(var i = 0; i < elements.length; ++i)
    {
    var binding = elements[i];
    
    if(binding.type == "bind-value")
      {
      if(binding.element.type == "checkbox")
        binding.element.checked = value.value;
      else if(binding.element.type == "radio")
        binding.element.checked = value.value;
      else if(binding.element.type == "text")
        binding.element.value = value.value;
      }
    else if(binding.type == "bind-continuousvalue")
      {
      if(binding.element.type == "text")
        binding.element.value = value.value;
      }
    else if(binding.type == "bind-enabled")
      binding.element.disabled = !value.value;
    }
    
  if(focusedElement != null )
    if((startSelection != null) && (endSelection != null))
      focusedElement.setSelectionRange(startSelection, endSelection);

  bindingInProgress = false;
  
  return "ok";
  }

function logmsg(message)
  {
  if(window.webkit != undefined)
    window.webkit.messageHandlers.logmessage.postMessage(message);
  else if(window.logmessage != undefined)
    window.logmessage.postMessage(message);
  else
    console.log(message);
  }
