<?php

  /**
   * Angie application upgrade system
   *
   * @package angie.library.application
   * @subpackage upgrader
   */
  final class AngieApplicationUpgrader {
    
    /**
     * Upgrader adapter
     *
     * @var AngieApplicationUpgraderAdapter
     */
    private static $adapter;
    
    /**
     * Initialize upgrader
     */
    static function init() {
      $adapter_class = APPLICATION_NAME . 'UpgraderAdapter';
      
      $adapter_class_path = APPLICATION_PATH . "/resources/$adapter_class.class.php";
      if(is_file($adapter_class_path)) {
        require_once $adapter_class_path;
        
        if(class_exists($adapter_class)) {
          $adapter = new $adapter_class();
          
          if($adapter instanceof AngieApplicationUpgraderAdapter) {
            self::$adapter = $adapter;
          } else {
            throw new InvalidInstanceError('adapter', $adapter, $adapter_class);
          } // if
        } else {
          throw new ClassNotImplementedError($adapter_class, $adapter_class_path);
        } // if
      } else {
        throw new FileDnxError($adapter_class_path);
      } // if
    } // init
    
    /**
     * Render installer dialog
     */
    static function render() {
      print '<!DOCTYPE html>';
      print '<html><head><title>' . AngieApplication::getName() . ' Upgrade Script</title>';
      print '<script type="text/javascript">' . file_get_contents(ANGIE_PATH . '/frameworks/environment/assets/foundation/javascript/jquery.official/jquery.js') . '</script>';
      print '<script type="text/javascript">' . file_get_contents(ANGIE_PATH . '/frameworks/environment/assets/foundation/javascript/jquery.plugins/jquery.form.js') . '</script>';
      print '<script type="text/javascript">' . file_get_contents(ANGIE_PATH . '/frameworks/environment/assets/upgrader/javascript/jquery.upgrader.js') . '</script>';
      print '<style type="text/css">' . file_get_contents(ANGIE_PATH . '/frameworks/environment/assets/foundation/stylesheets/reset.css') . '</style>';
      print '<style type="text/css">' . file_get_contents(ANGIE_PATH . '/frameworks/environment/assets/foundation/stylesheets/classes.css') . '</style>';
      print '<style type="text/css">' . file_get_contents(ANGIE_PATH . '/frameworks/environment/assets/upgrader/stylesheets/upgrader.css') . '</style>';
      print '</head>';
      
      print '<body><div id="application_upgrader">';
      
      $counter = 1;
      foreach(AngieApplicationUpgrader::getSections() as $section_name => $section_title) {
        print '<div class="upgrader_section" upgrader_section="' . $section_name . '">';
        print '<h1 class="head">' . $counter . '. <span>' . clean($section_title) . '</span></h1>';
        print '<div class="body">' . AngieApplicationUpgrader::getSectionContent($section_name) . '</div>';
        print '</div>';
        
        $counter++;
      } // foreach
      
      print '</div><p class="center">&copy;' . date('Y') . ' ' . AngieApplication::getVendor() . '. All rights reserved.</p><script type="text/javascript">$("#application_upgrader").upgrader({"name" : "' . AngieApplication::getName() . '"});</script>';
      print '</body></html>';
    } // render
    
    /**
     * List actions
     */
    static function listActions() {
      header("Content-Type: text/xml; charset=utf-8");
      
      print '<?xml version="1.0" encoding="UTF-8" ?>';
      print '<actions>';
      
      $current_version = self::$adapter->currentVersion();
      
      $available_scripts = self::$adapter->availableScripts($current_version);
      if($available_scripts) {
        foreach($available_scripts as $script) {
          $group = $script->getGroup();
          
          if($script->getActions()) {
            foreach($script->getActions() as $action => $description) {
              print '<action group="' . clean($group) . '" action="' . clean($action) . '">' . clean($description) . '</action>';
            } // foreach
          } // if
        } // foreach
      } // if
      
      print '</actions>';
      
      die();
    } // listActions
    
    /**
     * Execute given step
     * 
     * @param array $action
     */
    static function executeAction($action) {
      $email = isset($action['email']) && $action['email'] ? $action['email'] : '';
      $password = isset($action['password']) && $action['password'] ? $action['password'] : '';
      
      if($email && $password) {
        if(self::$adapter->validateBeforeUpgrade(array('email' => $email, 'pass' => $password))) {
          $response = self::$adapter->executeAction($action['group'], $action['action']);
          
          if(is_string($response)) {
            AngieApplicationUpgrader::breakActionExecution($response);
          } else {
            header('HTTP/1.1 200 OK');
          } // if
        } else {
          AngieApplicationUpgrader::breakActionExecution('Invalid user credentials');
        } // if
      } else {
        AngieApplicationUpgrader::breakActionExecution('Invalid user credentials');
      } // if
    } // executeAction
    
    /**
     * Break action execution
     * 
     * @param string $message
     */
    static private function breakActionExecution($message) {
      header('HTTP/1.1 500 Internal Server Error');
      die($message);
    } // breakActionExecution
    
    // ---------------------------------------------------
    //  Sections
    // ---------------------------------------------------
    
    /**
     * Return all installer sections
     * 
     * @return array
     */
    static function getSections() {
      return self::$adapter->getSections();
    } // getSections
    
    /**
     * Return initial content for a given section
     * 
     * @param string $name
     * @return string
     */
    static function getSectionContent($name) {
      return self::$adapter->getSectionContent($name);
    } // getSectionContent
    
    /**
     * Secuted section submission
     * 
     * @param string $name
     * @param mixed $data
     * @return boolean
     */
    static function executeSection($name, $data = null) {
      $response = '';
      
      if(self::$adapter->executeSection($name, $data, $response)) {
        header("HTTP/1.0 200 OK");
      } else {
        header("HTTP/1.0 409 Conflict");
      } // if
      
      print $response;
    } // executeSection
    
  }