<?php
/*
Plugin Name: Kob Admin
Plugin URI: http://mcfinley.ru
Description: Легковесный плагин для настройки кастомайзера в админке
Version: 1.0
Author: mcfinley
Author URI: http://mcfinley.ru
*/

defined( 'ABSPATH' ) or die( 'No script kiddies please!' );

  /* Fake class for meta rendering */
  if(!class_exists('WP_Customize_Control')) {

    class WP_Customize_Control{
      public $id;

      public function __construct($manager, $id, $args) {
        $this->id = $id;
      }

      public function value() {
        // get_post_meta($post_id, $key, $single);
      }

      public function link() {
        echo 'name="meta-box-' . $this->id . '"';
      }
    }
  }

  class KobAdminControl {

    private $name;

    public function getName(){
      return $this->name;
    }

    public function getData($data) {
      if (isset($data) && isset($data->{$this->getName()}))
        return $data->{$this->getName()};
      else
        return NULL;
    }

    private function setName($name){
      $this->name = $name;
      return $this;
    }

    public function __construct($name){
      $this->setName($name);
    }

    public function styles(){return array();}
    public function scripts(){return array();}

    public function className(){echo 'kob-admin-control';}

    public function update(){echo '';}
    public function initialize(){echo '';}
    public function serialization(){echo '';}
    public function bindListeners(){echo '';}

    public function render($id, $data){echo 'Kob Admin v1.0 : This KobAdminControl isnt filled. $id = ' . $id;}

    public function kobRender($id, $data){
      ?>
        <!-- Control <?php echo $this->getName() ?> in <?php echo $id ?> -->
        <div
          id="kob-admin-control-<?php echo $this->getName() ?>"
          class="kob-serialize <?php $this->className() ?>"
          data-name="<?php echo $this->getName() ?>"
          data-update="<?php $this->update() ?>"
          data-initialize="<?php $this->initialize() ?>"
          data-serialization="<?php $this->serialization() ?>"
          data-bind-listeners="<?php $this->bindListeners() ?>"
        >
          <?php $this->render($id, $data) ?>
        </div>
      <?php
    }

  }



  class KobAdminManyControl extends KobAdminControl {

    private $inputs;

    public function __construct($name, $inputs){
      parent::__construct($name);
      $this->inputs = $inputs;
    }

    public function scripts() {
      $result = array();
      foreach($this->inputs as $input) {
        $result = array_merge($result, $input->scripts());
      }
      return $result;
    }

    public function styles() {
      $result = array();
      foreach($this->inputs as $input) {
        $result = array_merge($result, $input->styles());
      }
      return $result;
    }

    public function className() {echo 'kob-many-control';}

    public function update() {
      ?>
        $(element).children().each(function(){
          updateElement(this, main, data.<?php echo $this->getName() ?>);
        });
      <?php
    }

    public function serialization() {
      ?>
        var serialized = {};
        $(element).children().each(function(){
          serialized[getElementName(this)] = serializeElement(this);
        });
        return serialized;
      <?php
    }

    public function bindListeners() {
      ?>
        $(element).children().each(function(){
          bindListenersToElement(this, id);
        });
      <?php
    }

    public function initialize() {
      ?>
        $(element).children().each(function(){
          initializeElement(this);
        });
      <?php
    }

    public function render($id, $data) {
      foreach($this->inputs as $input)
        $input->kobRender($id, $this->getData($data));
    }

  }



  class KobAdminControlManager extends WP_Customize_Control {

    public $type = 'text';

    private $input;

    private function setInput($input) {
      $this->input = $input;
      return $this;
    }

    public function getInput() {
      return $this->input;
    }

    public function __construct($manager, $id, $args = array(), $input = NULL) {
      parent::__construct($manager, $id, $args);
      //$manager->add_control()
      $this->setInput($input);

      add_action( 'admin_print_footer_scripts', array($this, 'print_includes') );
    }

    public function kobRender($json_value) {
      if($this->getInput()) {
        $data = json_decode($json_value);
        $this->getInput()->kobRender($this->id, $data);
      }
    }

    public function styles() {
      if ($this->getInput()) {
        return $this->getInput()->styles();
      }
    }

    public function scripts() {
      if ($this->getInput()) {
        return $this->getInput()->scripts();
      }
    }

    function print_includes() {

      foreach(array_merge($this->scripts(), $this->styles()) as $key => $script) {
        if(!(defined($key))){
          echo $script;
          define($key, 'test');
        }
      }

    }

    public function sub_content($id, $value) {
      ?>
        <!-- Content -->
        <div id='kob-manager-<?php echo $id ?>-content' class='kob-manager-content'>
          <?php $this->kobRender($value); ?>
        </div>
        <!-- /Content -->
      <?php
    }

    public function sub_scripts() {
      ?>

        <!-- Main functions -->
        <script>

          function updateElement(el, main, data) {
            var raw_code = $(el).attr('data-update');
            var updateFunction = new Function('element, main, data', raw_code);

            updateFunction(el, main, data);

          }

          function initializeElement(el) {
            var raw_code = $(el).attr('data-initialize');
            var initializeFunction = new Function('element', raw_code);
            initializeFunction(el);
          }


          function getElementName(el) {
            return $(el).attr('data-name');
          }


          function serializeElement(el) {

            var raw_code = $(el).attr('data-serialization');

            var serializeFunction = new Function('element', raw_code);

            return serializeFunction(el);

          }


          function serializeKobManager(id) {

            var kob_manager_content = {};

            $('#kob-manager-' + id + '-content').children().each(function(){
              kob_manager_content[getElementName(this)] = serializeElement(this);
            });

            $('#kob-manager-' + id + '-result').val(JSON.stringify(kob_manager_content));
            $('#kob-manager-' + id + '-result').keyup();

            $('#kob-manager-' + id + '-content').children().each(function(){
              updateElement(this, kob_manager_content, kob_manager_content);
            });

          }


          function bindListenersToElement(el, id) {
            var raw_code = $(el).attr('data-bind-listeners');
            var bindListenersFunction = new Function('element, id', raw_code);
            bindListenersFunction(el, id);
          }

          function primitiveBindListeners(el, id) {
            var _id = id;
            $(el).on('change',   function(){serializeKobManager(_id);});
          }

          function advancedBindListeners(el, id) {
            var _id = id;
            $(el).on('click',    function(){serializeKobManager(_id);});
            $(el).on('change',   function(){serializeKobManager(_id);});
            $(el).on('keypress', function(){serializeKobManager(_id);});
            $(el).on('keyup',    function(){serializeKobManager(_id);});
            $(el).on('keydown',  function(){serializeKobManager(_id);});
            $(el).on('focus',    function(){serializeKobManager(_id);});
          }


          function bindListeners(id) {
            $('#kob-manager-' + id + '-content').children().each(function(){
              bindListenersToElement(this, id);
            });
          }


          function initializeElements(id) {
            $('#kob-manager-' + id + '-content').children().each(function(){
              initializeElement(this);
            });
          }

          $(document).ready(function(){
            initializeElements('<?php echo $this->id ?>');
            bindListeners('<?php echo $this->id ?>');
            serializeKobManager('<?php echo $this->id ?>');
          });


        </script>
        <!-- /functions -->

      <?php
    }

    public function sub_link(){
      ob_start();
      $this->link();
      return ob_get_clean();
    }

    public function sub_form($id, $sub_link) {
      ?>

        <!-- Serialized form -->
        <input id='kob-manager-<?php echo $id ?>-result' style='display:none' class='kob-manager-result' type="text" <?php echo $sub_link ?> />
        <!-- /form -->

      <?php
    }

    public function render_content() {

      $this->sub_content($this->id, $this->value());
      $this->sub_scripts();
      $this->sub_form($this->id, $this->sub_link());

    }

    public function render_meta($post_id, $key) {

      $value = get_post_meta($post_id, $key);

      $value = ($value && count($value) > 0) ? $value[0] : NULL;

      $this->sub_content($this->id, $value);
      $this->sub_scripts();
      $this->sub_form($this->id, $this->sub_link());

    }

  }


  /* Common controls */

  require ( 'Common/CheckboxControl.php' );
  require ( 'Common/ConditionableControl.php' );
  require ( 'Common/DecoratorControl.php' );
  require ( 'Common/DraggableControl.php' );
  require ( 'Common/DropdownControl.php' );
  require ( 'Common/HiddenControl.php' );
  require ( 'Common/ImageControl.php' );
  require ( 'Common/InputControl.php' );
  require ( 'Common/LabelControl.php' );
  require ( 'Common/RadioControl.php' );
  require ( 'Common/RepeaterChoiceControl.php' );
  require ( 'Common/RepeaterControl.php' );
  require ( 'Common/RepeaterTypeTwoControl.php' );
  require ( 'Common/SelectControl.php' );
  require ( 'Common/SpinControl.php' );
  require ( 'Common/SwitchableDropdownControl.php' );
  require ( 'Common/SwitchControl.php' );
  require ( 'Common/TabsControl.php' );
  require ( 'Common/TextareaControl.php' );
  require ( 'Common/TextControl.php' );
  require ( 'Common/WysiwygControl.php' );
  require ( 'Common/IconControl.php' );
  require ( 'Common/BlockedControl.php' );


  /* Custom controls */

  require ( 'Custom/ColorsControl.php' );
  require ( 'Custom/FontControl.php' );
  require ( 'Custom/SocialAccountsControl.php' );
  require ( 'Custom/SizeControl.php' );
  require ( 'Custom/GalleryControl.php' );
  require ( 'Custom/NewGalleryControl.php' );
  require ( 'Custom/SlideControl.php' );
  require ( 'Custom/SliderControl.php' );


  function isObjectOrArray($a) {
    return is_array($a) || is_object($a);
  }

  # Join tow object recursively
  function joinObjects($a, $b) {
    $a = (array)$a;
    $b = (array)$b;
    $r = $a;
    foreach($b as $k => $v) {
      if (isObjectOrArray($v))
        $r[$k] = joinObjects($a[$k], $b[$k]);
      else
        if(isset($b[$k]))
          $r[$k] = $b[$k];
        else
          $r[$k] = $a[$k];
    }
    return (array)$r;
  }

  /* Retrieving global kob object settings from customizer */
  function get_kob_object($id) {
    $settings = retrieveThemeSettings();

    $option = get_option( $id );
    $mod    = get_theme_mod( $id );

    # Find settings in default theme settings and replace not filled with defaults
    foreach($settings as $setting) {
      if($setting['settings'] == $id) {
        $mod_o = (array)json_decode($mod);
        $set_o = (array)json_decode($setting['default']);
        $mod = json_encode(joinObjects($set_o, $mod_o));
      }
    }

    if ( $option != $mod && $mod)
      update_option( $id, $mod );

    return json_decode($mod);

  }



  /* Retrieving kob object settings from post meta */

  function get_kob_meta($id, $field){

    $data = get_post_meta($id, $field);

    if(is_array($data) && count($data) > 0)
      $data = json_decode($data[0]);
    else
      $data = NULL;

    return $data;
  }



  /* Building settings interface from object */

  function buildInterface($object) {

    if ( is_string($object) )
      $object = json_decode( $object );

    if ( is_object($object) )
      $object = (array)$object;

    foreach($object as $name => $config) {

      $type  = $config->type;
      $type .= 'Control';

      $args  = $config->args;

      if ( isset($config->inner) ) {
        $inner = $config->inner;
        $inner = buildInterface($inner);
      } else
        $inner = NULL;

      return new $type($name, (array)$args, $inner);

    }

  }




  /* Building WP control */

  // function buildControl($wp_customize, $object, $setting) {
  //
  //   return new KobAdminControlManager(
  //     $wp_customize,
  //     'animation_settings',
  //     array(
  //       'section' => 'section_animation',
  //       'settings' => 'animation_settings'
  //     ),
  //     buildInterface($object)
  //   );
  //
  // }
