<?php

require_once "WEB-INF/php/inc.php";

if (! admin_init()) {
  return;
}

$webapp = $g_mbean_server->lookup($_GET['id']);

$request = quercus_servlet_request();
$user = quercus_get_request()->getUserPrincipal();
$client = @new Java("com.caucho.server.admin.WebAppDeployClient");
$deploy_enabled = check_deploy_enabled($request->isSecure());

print_title("deploy", "Deploy new application");

if ($deploy_enabled) {
  $action = $_POST['action'];

  if ($action == 'deploy') {
    deploy();
  }
}

display_deploy_form($g_mbean_server);

function check_deploy_enabled($is_secure)
{
  global $g_server_index;

  if (! $is_secure)
    return 0;

  $mbean_server = new MBeanServer();
  $server = $mbean_server->getServer();
  $server_index = $server->SelfServer->ClusterIndex;

  if ($g_server_index != $server_index)
    return 0;

  return 1;
}

function display_deploy_form($mbean_server)
{
  global $deploy_enabled;

  if ($deploy_enabled) {
    $disabled = "";
  }
  else {
    $disabled = "disabled='disabled'";
    echo "<div class='warn'>";
    echo gettext('Actions can only be performed on a local server and over a secure connection (SSL)."');

    $host = $_SERVER["SERVER_NAME"];
    $port = $_SERVER["SERVER_PORT"];
    $uri = $_SERVER["REQUEST_URI"];

    if ($port == 8080) {
      $url = htmlspecialchars("https://${host}:8443$uri");
    }
    else {
      $url = htmlspecialchars("https://$host$uri");
    }

    echo " Try <a href='$url'>$url</a>";

    echo "</div>";
  }

  ?>
<form id='deploy' enctype='multipart/form-data' method='post' action="#">
  <input type='hidden' name='action' value='deploy'/>

  <div class='form-input-block'>
    <div id='file-title' class='form-input-title'><label for='application'><?= gettext('Application archive file')?></label></div>
    <div class='form-input-input'>
      <input type='file' name='application' id='application'/>
    </div>
    <div class='form-input-help'><?= gettext('The .war file to upload')?></div>
    <div id='file-info-box' class='info-box ui-state-highlight' style='display:none'></div>
  </div>

  <div class='form-input-block'>
    <div id='name-title' class='form-input-title'><label for='name'><?= gettext('Name')?></label></div>
    <div class='form-input-input'>
      <input type='text' name='name' value='<?= $_GET['update-name'] ?>' class='required' id='name'/>
    </div>
    <div class='form-input-help'><?= gettext('The context root and name of the application')?></div>
  </div>

  <div class='form-input-block'>
    <div class='form-input-title'>Version</div>
    <div class='form-input-input'>
      <input type='number' min='0' size='3' name='version-major'
             title='Major Version Number' value='0' class='required'
             id='version-major'/>
      <input type='number' min='0' size='3' name='version-minor'
             title='Minor Version Number' value='0' class='required'
             id='version-minor'/>
      <input type='number' min='0' size='3' name='version-micro'
             title='Micro Version Number' value='0' class='required'
             id='version-micro'/>
      <input type='text' name='version-qualifier'
             title='Version Qualifier (free form)' value=''
             id='version-qualifier'/>
    </div>
    <div class='form-input-help'>The version for the application, using the
      <label for='version-major'>&lt;major></label>.<label for='version-minor'>
        &lt;minor></label>.<label for='version-micro'>&lt;micro></label>.<label
        for='version-qualifier'>&lt;qualifier></label> format.
    </div>
  </div>

  <div class='form-input-block'>
    <div class='form-input-title'><label for='commit-message'><?= gettext('Commit  message')?></label></div>
    <div class='form-input-input'>
      <textarea name='commit-message' id='commit-message' rows='2' cols='80'></textarea>
    </div>
    <div class='form-input-help'><?= gettext('A message to save along with this deployment.')?></div>
  </div>

  <div class='switch' id='deploy-advanced-options' style='margin-bottom: 2em;'><?= gettext('Advanced Options')?></div>
  <div class='toggle-deploy-advanced-options option-box' style="display: none">

    <div class='form-input-block'>
      <div class='form-input-title'><?=gettext('Host')?></div>
      <div class='form-input-input'>
        <fieldset>
          <legend><?= gettext('Host:')?></legend>
          <input class='host' type='radio' name='host' value='default' checked='checked' id='default-host'/>
          <label for='default-host'><?= gettext('Deploy to default host')?></label>
          <br/>
        <span class='another-host'>
          <input type='radio' name='host' value='' id='another-host'/>
          <label for='another-host'><?= gettext('Deploy to another host:')?></label>
          <input type='text' name='host' value='' disabled='disabled' id='another-host-name'/>
        </span>
        </fieldset>
      </div>
      <div class='form-input-help'><label
        for='another-host-name'><?= gettext('The virtual host where the application will appear.')?></label>
      </div>
    </div>

    <div class='form-input-block'>
      <div class='form-input-title'><?= gettext('Stage')?></div>
      <div class='form-input-input'>
        <fieldset>
          <legend><?= gettext('Stage')?></legend>
          <input class='stage' type='radio' name='stage' value='production' checked='checked' id='default-stage'/>
          <label for='default-stage'><?= gettext('Deploy to production')?></label>
          <br/>
        <span class='another-stage'>
          <input type='radio' name='stage' value='' id='another-stage'/>
          <label for='another-stage'><?= gettext('Deploy to another stage:')?></label>
          <input type='text' name='stage' value='' disabled='disabled' id='another-stage-name'/>
        </span>
        </fieldset>
      </div>
      <div class='form-input-help'><label
        for='another-stage-name'><?= gettext('The stage where the application will appear.')?></label>
      </div>
    </div>
  </div>

  <div id='deploy-info-box' class='info-box ui-state-highlight' style='display:none'></div>

  <input id="submit-button" class='deploy' type='submit' value='<?= gettext('Deploy')?>' <?= $disabled ?>/>
</form>
<?
}

function deploy()
{
  global $user;
  global $client;
  global $g_mbean_server;
  global $g_server_index;

  $commit = new Java("com.caucho.env.repository.CommitBuilder");

  $commit->type("webapp");

  $stage = htmlspecialchars($_POST['stage']);

  if ($stage)
    $commit->stage($stage);
  else
    $commit->stage("production");

  $host = htmlspecialchars($_POST['host']);

  if (! $host)
    $host = "default";

  $name = htmlspecialchars($_POST['name']);

  if ($name == '/')
    $name = "/ROOT";

  if ($name[0] != '/')
    $name = '/' . $name;

  $commit->tagKey($host . $name);

  $major = $_POST['version-major'];
  $minor = $_POST['version-minor'];
  $micro = $_POST['version-micro'];
  $qualifier = $_POST['version-qualifier'];

  if ($major || $minor || $micro || $qualifier) {
    $commit->version(htmlspecialchars($major),
                     htmlspecialchars($minor),
                     htmlspecialchars($micro),
                     htmlspecialchars($qualifier));
  }

  if ($_POST['commit-message'])
    $commit->message($_POST['commit-message']);
  else
    $commit->message("updated via resin-admin web form");

  $commit->attribute("user", $user);

  $path = $_FILES['application']['tmp_name'];

  if (! $path) {
    ?>
  <div class='ui-state-error info-box' style='margin-bottom: 0.5em'>
    <span class='ui-icon ui-icon-alert' style='float: left; margin: 15px 5px;'></span>

    <h3><?= gettext('Deploy failed')?></h3>

    <p><strong><?= gettext('Please specify an application archive file')?></strong></p>
  </div>
  <?
  }
  else {
    $client->commitArchive($commit, $path);

    $date = $commit->getAttributes()['date'];
    $message = $commit->getAttributes()['message'];

?>
<div class='ui-state-highlight info-box' style='margin-bottom: 0.5em'>
  <span class='ui-icon ui-icon-info' style='float: left; margin: 15px 5px;'></span>

  <h3><?= gettext('Successfully deployed application')?></h3>

  <p>
    <?php
    $success_message = gettext('The application may take a few moments to be propagated throughout the cluster. Please check the <a href=\'?q=webapp&amp;s=$g_server_index\'>webapp</a> page for more information.');
    $success_message = preg_replace('/\$g_server_index/', $g_server_index, $success_message);
    echo $success_message;
    ?>
  </p>

  <div><b><?= gettext('Name:')?></b><?= $name ?></div>
  <div><b><?= gettext('Version:')?></b><?= $commit->getVersion() ?></div>
  <div><b><?= gettext('Deploy date:')?></b><?= $date ?></div>
  <div><b><?= gettext('Commit message:')?></b><?= $message ?></div>
</div>
<?
  }
}

function javascript_autocomplete()
{
  global $client;
  global $g_mbean_server;

  $tags = $client->queryTags("[^/]*/webapp/.*");

  $stages = array("production");
  $hosts = array();

  foreach ($tags as $tag) {
    $elements = explode("/", $tag->getTag());
    array_push($stages, "'{$elements[0]}'");
    array_push($hosts, "'{$elements[2]}'");
  }

  $stages = array_unique($stages);
  $hosts = array_unique($hosts);

  $stage_json = json_encode($stages);
  $host_json = json_encode($hosts);

  $javascript = <<<EOF
    var stages = ${stage_json};
    $("input:text.stage").autocomplete({ source: stages });
    var hosts = ${host_json};
    $("input:text.host").autocomplete({ source: hosts });

EOF;

  $webapps = $g_mbean_server->query("resin:*,type=WebApp");
  $apps = array();

  foreach ($webapps as $webapp) {
    $contextPath = $webapp->getContextPath();

    if ($contextPath == "")
      $contextPath = "/ROOT";

    $key = $webapp->getHost()->getName() . $contextPath;
    $metadata = $webapp->getRepositoryMetaData();

    if (count($metadata) == 0) {
      $apps[$key] = array("rootDirectory" => $webapp->getRootDirectory());
    }
    else {
      $apps[$key] = $metadata;
    }
  }

  $apps_json = json_encode($apps);
  $javascript .= <<<EOF
    var apps = {$apps_json}; 

EOF;

  return $javascript;
}

function javascript_deploy_form()
{
  $triggerChange = $_GET['update-name'] ? "true" : "false";

  $javascript = javascript_autocomplete();

  $message_app_must_be_war_file = gettext('Application archive must be a .war file');

  $message_updating_existing_app = gettext('Updating existing application');
  $message_name = gettext('Name:');
  $message_current_version = gettext('Current version:');
  $message_deploy_date = gettext('Deploy date:');
  $message_commit_message = gettext('Commit message:');

  $message_overwriting_file_system_based_application = 'Overwriting file system-based application';
  $message_app_already_deployed_override_warning = gettext('An application with the same name is already deployed on this system, but was not deployed via the distributed deployment mechanism. <p><strong>This operation will overwrite the existing application and is not reversable.</strong></p>');
  $message_root_directory = gettext('Root directory:');

  $message_please_correct_the_following_problems = gettext('Please correct the following problems problems');

  $javascript .= <<<EOF
    var applicationNameInput = $("input[name=name]");
    var applicationFileInput = $("input:file[name='application']");
    var hostRadio = $("input:radio[name=host]");
    var anotherHostRadio = $(".another-host input:radio");
    var anotherHostInput = $(".another-host input:text");
    var fileInfoBox = $("#file-info-box");
    var infoBox = $("#deploy-info-box");
    var submitInput = $("#submit-button");

    applicationFileInput.change(function() {
      var filename = applicationFileInput.val();
      var match = /(.*(\/|\\\\))*(.*)\.(war|jar|zip)$/.exec(filename);

      if (! match) {
        fileInfoBox.addClass("ui-state-error");
        fileInfoBox.html("<span class='ui-icon ui-icon-alert' " +
                     "style='float: left; margin: 15px 5px;'></span>" +
                     "<h3>$message_app_must_be_war_file</h3>");

        fileInfoBox.show();

        submitInput.attr("disabled", true);

        return;
      }

      fileInfoBox.removeClass("ui-state-error");
      fileInfoBox.hide();

      submitInput.attr("disabled", false);

      if (applicationNameInput.val() == "") {
        applicationNameInput.val(match[3]);
        applicationNameInput.change();
      }
    });

    applicationNameInput.change(function() {
      var contextPath = applicationNameInput.val();

      if (contextPath == '/') 
        contextPath = "/ROOT";

      var appKey = hostRadio.val();

      if (contextPath.charAt(0) == '/')
        appKey += contextPath;
      else 
        appKey += '/' + contextPath;

      if (appKey in apps) {
        var app = apps[appKey];

        if ("tag" in app) {
          var version = app["version"];
          var match = /^([^.]+)\.([^.]+)\.([^.]+)(\.([.*]))?$/.exec(version);

          if (match) {
            var major = match[1];
            var minor = match[2];
            var micro = match[3];

            var majorInput = $("input[name=version-major]");
            var minorInput = $("input[name=version-minor]");
            var microInput = $("input[name=version-micro]");
            var qualifierInput = $("input[name=version-qualifier]");

            if (majorInput.val() == "0"
                && minorInput.val() == "0"
                && microInput.val() == "0"
                && qualifierInput.val() == "") {
              majorInput.val(major);
              minorInput.val(minor);
              microInput.val(parseInt(micro) + 1);

              if (match.length > 5) {
                var qualifier = match[5];
                qualifierInput.val(qualifier);
              }
            }
          }

          infoBox.addClass("ui-state-highlight");
          infoBox.removeClass("ui-state-error");
          infoBox.html("<div style='margin-bottom: 0.5em'>" +
                       "<span class='ui-icon ui-icon-info' " +
                       "style='float: left; margin: 0px 5px;'></span>" + 
                       "<h3>$message_updating_existing_app</h3></div>" +
                       "<div><b>$message_name</b> " + contextPath + "</div>" +
                       "<div><b>$message_current_version</b> " + version + "</div>" +
                       "<div><b>$message_deploy_date</b> " + app["date"] + "</div>" +
                       "<div><b>$message_commit_message</b> " + app["message"] + "</div>");
          infoBox.show();
        }
        else {
          infoBox.removeClass("ui-state-highlight");
          infoBox.addClass("ui-state-error");
          infoBox.html("<div style='margin-bottom: 0.5em'>" +
                       "<span class='ui-icon ui-icon-alert' " +
                       "style='float: left; margin: 0px 5px;'></span>" + 
                       "<h3>$message_overwriting_file_system_based_application</h3>" +
                       "</div>" +
                       "<p>$message_app_already_deployed_override_warning</p>" +
                       "<div><b>$message_name</b> " + contextPath + "</div>" +
                       "<div><b>$message_root_directory</b> " + app["rootDirectory"] + "</div>");
          infoBox.show();
        }
      }
      else {
        infoBox.hide();
      }
    });

    if ($triggerChange)
      applicationNameInput.change();

    hostRadio.change(function() {
      if (anotherHostRadio.attr("checked")) {
        $(".another-host").css("color", "black");
        anotherHostInput.attr('disabled', false);
      }
      else {
        $(".another-host").css("color", "#999");
        anotherHostInput.attr('disabled', true);
      }
    });

    var stageRadio = $("input:radio[name=stage]");
    var anotherStageRadio = $(".another-stage input:radio");
    var anotherStageInput = $(".another-stage input:text");

    stageRadio.change(function() {
      if (anotherStageRadio.attr("checked")) {
        $(".another-stage").css("color", "black");
        anotherStageInput.attr('disabled', false);
      }
      else {
        $(".another-stage").css("color", "#999");
        anotherStageInput.attr('disabled', true);
      }
    });

    $("input:submit").click(function() { 
      var problems = "";

      if (applicationFileInput.val() == "") {
        $("#file-title").effect("highlight");
        problems += "<p>Select an application archive</p>";
      }

      if (applicationNameInput.val() == "") {
        $("#name-title").effect("highlight");
        problems += "<p>Enter an application name</p>";
      } 

      if (problems.length > 0) {
        infoBox.addClass("ui-state-error");
        infoBox.html("<span class='ui-icon ui-icon-alert' " +
                     "style='float: left; margin: 15px 5px;'></span>" + 
                     "<h3>$message_please_correct_the_following_problems</h3>");
        infoBox.show();
        return false;
      }

      return true;
    });
EOF;

  return $javascript;
}

if ($deploy_enabled)
  $javascript = javascript_deploy_form();

display_footer($g_page, $javascript);
?>
