<?php

class WDFHelper {
  ////////////////////////////////////////////////////////////////////////////////////////
  // Events                                                                             //
  ////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////
  // Constants                                                                          //
  ////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////
  // Variables                                                                          //
  ////////////////////////////////////////////////////////////////////////////////////////
  /**
   * Component name.
   *
   * @var    string
   */
  private static $com_name;

  private static $controller;

  /**
   * Map of generated models.
   *
   * @var    Array
   */
  private static $models_map;

  ////////////////////////////////////////////////////////////////////////////////////////
  // Constructor & Destructor                                                           //
  ////////////////////////////////////////////////////////////////////////////////////////
  /**
   * Init variables and require all files in framework
   */
  public static function init($com_name = '') {
    self::$com_name = $com_name != '' ? $com_name : (isset($_GET['page']) ? esc_html($_GET['page']) : '');
    self::require_dir(WD_E_DIR . DS . 'framework');
    self::require_dir(WD_E_DIR . DS . 'tables');
    if (!is_admin()) {
      if (WDFInput::get_controller() == null) {
        WDFInput::set('controller', WDFInput::get('view'));
      }
      if (WDFInput::get_task() == null) {
        WDFInput::set('task', WDFInput::get('layout'));
      }
    }
    self::com_require('controllers' . DS . 'controller.php');
    self::com_require('models' . DS . 'model.php');
    self::com_require('views' . DS . 'view.php');
  }

  ////////////////////////////////////////////////////////////////////////////////////////
  // Public Methods                                                                     //
  ////////////////////////////////////////////////////////////////////////////////////////
  /**
   * Get component name
   *
   * @return    string    name of the component
   */
  public static function get_com_name() {
    return WD_E_NAME;
  }

  /**
   * Require class starting from component directory
   *
   * @param    string $class_path path of the class to require
   */
  public static function com_require($class_path) {
    require_once WDFPath::get_com_path('admin') . DS . $class_path;
  }

  public static function get_controller() {
    if (self::$controller == NULL) {
      $input_controller = WDFInput::get_controller();
      if ($input_controller) {
        $controller_path = WDFPath::get_com_path('admin') . '/controllers/' . $input_controller . '.php';
        if (file_exists($controller_path)) {
          require_once $controller_path;
        }
      }
      $controller_class = ucfirst(self::get_com_name()) . 'Controller' . ucfirst($input_controller);
      self::$controller = new $controller_class();
    }
    return self::$controller;
  }

  public static function get_model($type = '', $is_frontend_ajax = false) {
    if (self::$models_map == NULL) {
      self::$models_map = array();
    }
    if ($type == '') {
      $input_controller = WDFInput::get_controller();
      $type = $input_controller;
    }
    if (isset(self::$models_map[$type]) == FALSE) {
      require_once WDFPath::get_com_path('admin', $is_frontend_ajax) . DS . 'models' . DS . $type . '.php';
      $model_class = ucfirst(self::get_com_name()) . 'Model' . ucfirst($type);
      self::$models_map[$type] = new $model_class;
    }
    return self::$models_map[$type];
  }

  public static function redirect($controller = '', $task = '', $cid = '', $params = '', $msg = '', $msgType = 'message', $ajax = FALSE) {
    if ($controller == '') {
      $controller = WDFInput::get_controller();
    }
    $url_parts = array();
    if ($controller != '') {
      $url_parts[] = 'page=wde_' . $controller;
    }
    if ($task != '') {
      $url_parts[] = 'task=' . $task;
    }
    if ($cid != '') {
      $url_parts[] = 'cid[]=' . $cid;
    }
    if ($params != '') {
      $url_parts[] = $params;
    }
    if ($msg != '') {
      $url_parts[] = 'msg=' . $msg;
    }
    /*if ($msgType != '') {
      $url_parts[] = 'msgType=' . $msgType;
    }*/

    $action = $ajax ? 'admin-ajax.php?action=wde_ajax&' : 'admin.php?';

    if (is_admin()) {
      /* For cid[]*/
      header("Location: " . $action . implode('&', $url_parts));
      exit;
    }
  }

  public static function get_image_original_url($image) {
    return str_replace("/thumb", "", $image);
  }
  
  public static function show_error($code) {
    $options = WDFHelper::get_model('options', true)->get_options();
    wp_redirect(WDFPath::add_pretty_query_args(get_permalink($options->option_systempages_page), $options->option_endpoint_systempages_errnum, $code, TRUE));
    exit;
  }

  ////////////////////////////////////////////////////////////////////////////////////////
  // Getters & Setters                                                                  //
  ////////////////////////////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////////////
  // Private Methods                                                                    //
  ////////////////////////////////////////////////////////////////////////////////////////
  /**
   * Require framework class
   *
   * @param    string $path name of the class to require
   */
  private static function framework_require($path) {
    require_once WD_E_DIR . DS . 'framework' . DS . $path;
  }

  /**
   * Require php files in specified folder
   *
   * @param    string $dir_path name of the dir of files
   * @param    boolean $include_subdirs include subdirectories
   */
  private static function require_dir($dir_path, $include_subdirs = TRUE) {
    $files = scandir($dir_path);
    foreach ($files as $file) {
      if (($file == '.') || ($file == '..')) {
        continue;
      }
      $file = $dir_path . DS . $file;

      if (is_dir($file) == TRUE) {
        self::require_dir($file);
      }
      else {
        if ((is_file($file) == TRUE)
          && (pathinfo($file, PATHINFO_EXTENSION) == 'php')) {
          require_once $file;
        }
      }
    }
  }

  /**
   * Get product orders.
   *
   * @since 2.0.14
   *
   * @return object of product orders
  */
  // public $order_product_rows;
  public static function get_order_product_rows() {
    // if ($this->order_product_rows == null) {
      global $wpdb;
      $j_user = wp_get_current_user();

      $model_options = WDFHelper::get_model('options', true);
      $options = $model_options->get_options();
      $decimals = $options->option_show_decimals == 1 ? 2 : 0;

      $row_default_currency = WDFDb::get_row('currencies', '`default` = 1');

      $query = 'SELECT T_ORDER_PRODUCTS.id';
      $query .= ', T_ORDER_PRODUCTS.product_id';
      $query .= ', T_ORDER_PRODUCTS.product_parameters';
      $query .= ', T_ORDER_PRODUCTS.product_parameters_price';
      $query .= ', T_ORDER_PRODUCTS.product_count';
      $query .= ', T_PRODUCTS.post_title AS product_name';
      $query .= ', T_ORDER_PRODUCTS.product_parameters AS product_parameters_json';
      $query .= ' FROM ' . $wpdb->prefix . 'ecommercewd_orderproducts AS T_ORDER_PRODUCTS';
      $query .= ' LEFT JOIN ' . $wpdb->prefix . 'posts AS T_PRODUCTS ON T_ORDER_PRODUCTS.product_id = T_PRODUCTS.ID';
      $query .= ' WHERE T_ORDER_PRODUCTS.order_id = 0';
      if (is_user_logged_in()) {
        $query .= ' AND T_ORDER_PRODUCTS.j_user_id = ' . $j_user->ID;
      } else {
        $order_product_rand_ids = WDFInput::cookie_get_array('order_product_rand_ids');
        if (empty($order_product_rand_ids) == false) {
          $query .= ' AND T_ORDER_PRODUCTS.j_user_id = 0';
          $query .= ' AND T_ORDER_PRODUCTS.rand_id IN (' . implode(',', $order_product_rand_ids) . ')';
        } else {
          $query .= ' AND 0';
        }
      }
      $query .= ' ORDER BY T_ORDER_PRODUCTS.id ASC';
      $order_product_rows = $wpdb->get_results($query);

      if ($wpdb->last_error) {
        echo $wpdb->last_error;
        return false;
      }
      // additional data
      if (is_array($order_product_rows)) {
        foreach ($order_product_rows as $order_product_row) {
          $order_product_row->product_price = esc_attr(get_post_meta($order_product_row->product_id, 'wde_price', TRUE));
          $order_product_row->product_amount_in_stock = esc_attr(get_post_meta($order_product_row->product_id, 'wde_amount_in_stock', TRUE));
          $order_product_row->product_unlimited = esc_attr(get_post_meta($order_product_row->product_id, 'wde_unlimited', TRUE));
          $url = '';
          if (!has_post_thumbnail($order_product_row->product_id)) {
            $image_ids_string = get_post_meta($order_product_row->product_id, 'wde_images', TRUE);
            $image_ids = explode(',', $image_ids_string);
            if (isset($image_ids[0]) && is_numeric($image_ids[0]) && $image_ids[0] != 0) {
              $image_id = (int) $image_ids[0];
              $url = wp_get_attachment_url($image_id);
            }
          }
          else {
            $url = wp_get_attachment_url(get_post_thumbnail_id($order_product_row->product_id));
          }
          $order_product_row->product_image = $url;
          
          $tax = wp_get_object_terms($order_product_row->product_id, 'wde_taxes');
          $tax_id = isset($tax[0]->term_id) ? $tax[0]->term_id : 0;
          $tax = get_option("wde_taxes_" . $tax_id);
          $order_product_row->product_tax_rate = $tax['rate'];
          
          $discount = wp_get_object_terms($order_product_row->product_id, 'wde_discounts');
          $discount_id = isset($discount[0]->term_id) ? $discount[0]->term_id : 0;
          $discount = get_option("wde_discounts_" . $discount_id);
          $order_product_row->product_discount_rate = $discount['rate'];
          
          // product url
          $order_product_row->product_url = get_permalink($order_product_row->product_id);

          // taxes and discounts
          $order_product_row->product_discount_rate = WDFText::float_val($order_product_row->product_discount_rate, $decimals);
          $order_product_row->product_tax_rate = WDFText::float_val($order_product_row->product_tax_rate, $decimals);

          // price data
          if ($row_default_currency->sign_position == 0) {
            $order_product_row->product_base_price_text = $row_default_currency->sign . WDFText::wde_number_format($order_product_row->product_price, $decimals);
          }
          else {
            $order_product_row->product_base_price_text = WDFText::wde_number_format($order_product_row->product_price, $decimals) . $row_default_currency->sign;
          }
          $order_product_row->product_price_text = WDFText::wde_number_format($order_product_row->product_price + $order_product_row->product_parameters_price, $decimals);
          $order_product_row->product_final_price = (WDFText::float_val($order_product_row->product_price, $decimals) + WDFText::float_val($order_product_row->product_parameters_price, $decimals)) * (1 - $order_product_row->product_discount_rate / 100) * (1 + $order_product_row->product_tax_rate / 100);

          $order_product_row->product_final_price_text = '';
          if (WDFText::wde_number_format($order_product_row->product_final_price, $decimals) != WDFText::wde_number_format(0, $decimals)) {
            $order_product_row->product_final_price_text = WDFText::wde_number_format($order_product_row->product_final_price, $decimals);
            $order_product_row->product_final_price_text = $row_default_currency->sign_position == 0 ? $row_default_currency->sign . $order_product_row->product_final_price_text : $order_product_row->product_final_price_text . $row_default_currency->sign;
          }
          ob_start();
          if ($order_product_row->product_discount_rate) {
            ?>
            <span><?php echo __('Discount', 'wde') . ':&nbsp;' . $order_product_row->product_discount_rate . '%'; ?></span>
            <br />
            <?php
          }
          if ($order_product_row->product_tax_rate) {
            ?>
            <span><?php echo __('Tax', 'wde') . ':&nbsp;' . $order_product_row->product_tax_rate . '%'; ?></span>
            <?php
          }
          $order_product_row->product_final_price_info = WDFTextUtils::remove_html_spaces(ob_get_clean());

          // amount in stock
          if ($order_product_row->product_unlimited == 1) {
            $order_product_row->product_available = true;
            $order_product_row->product_availability_msg = __('In stock', 'wde');
            $order_product_row->stock_class = 'wd_in_stock';
          }
          elseif ($order_product_row->product_amount_in_stock > 0) {
            $order_product_row->product_available = true;
            $order_product_row->product_availability_msg = __('In stock', 'wde') . ': ' . $order_product_row->product_amount_in_stock;
            $order_product_row->stock_class = 'wd_in_stock';
          }
          else {
            $order_product_row->product_available = false;
            $order_product_row->product_availability_msg = __('Out of stock', 'wde');
            $order_product_row->stock_class = 'wd_out_of_stock';
          }
          // parameter datas
          $product_parameter_datas = self::get_product_parameter_datas($order_product_row->product_id, $order_product_row->id, $order_product_row->product_parameters_json);
          if ($product_parameter_datas === false) {
            WDFHelper::show_error(2);
          }
          $order_product_row->product_parameter_datas = $product_parameter_datas;
          // subtotal
          $order_product_row->subtotal = $order_product_row->product_final_price * $order_product_row->product_count;

          $order_product_row->subtotal_text = '';
          if (WDFText::wde_number_format($order_product_row->subtotal, $decimals) != WDFText::wde_number_format(0, $decimals)) {
            $order_product_row->subtotal_text = WDFText::wde_number_format($order_product_row->subtotal, $decimals);
            $order_product_row->subtotal_text = $row_default_currency->sign_position == 0 ? $row_default_currency->sign . $order_product_row->subtotal_text : $order_product_row->subtotal_text . $row_default_currency->sign;
          }
          // add currency symbols
          if ($row_default_currency->sign_position == 0) {
            $order_product_row->product_price_text = $row_default_currency->sign . $order_product_row->product_price_text;
          }
          else {
            $order_product_row->product_price_text = $order_product_row->product_price_text . $row_default_currency->sign;
          }
        }
      }
      // $this->order_product_rows = $order_product_rows;    
    // }
    // return $this->order_product_rows;
    return $order_product_rows;
  }

  /**
   * Get product orders total price.
   *
   * @since 2.0.14
   *
   * @return string product orders total price.
  */
  public static function get_order_products_total_price_text() {
    $model_options = WDFHelper::get_model('options', true);
    $options = $model_options->get_options();

    $row_default_currency = WDFDb::get_row('currencies', '`default` = 1');

    $order_product_rows = self::get_order_product_rows();

    $total = 0;
    if (is_array($order_product_rows)) {
      foreach ($order_product_rows as $order_product_row) {
        $total += $order_product_row->subtotal;
      }
    }
    $decimals = $options->option_show_decimals == 1 ? 2 : 0;
    
    $total_text = '';
    if (WDFText::wde_number_format($total, $decimals) != WDFText::wde_number_format(0, $decimals)) {
      $total_text = WDFText::wde_number_format($total, $decimals);
      $total_text = $row_default_currency->sign_position == 0 ? $row_default_currency->sign . $total_text : $total_text . $row_default_currency->sign;
    }
    return $total_text;
  }

  /**
   * Get random id for product order.
   *
   * @since 2.0.14
   *
   * @return int random id for product order.
  */
  public static function get_order_product_rand_id() {
    global $wpdb;
    $query = 'SELECT rand_id';
    $query .= ' FROM ' . $wpdb->prefix . 'ecommercewd_orderproducts';
    $existing_rand_ids = $wpdb->get_col();
    if ($wpdb->last_error) {
      return false;
    }

    do {
      $rand_id = rand(10000000, 99999999);
    } while (in_array($rand_id, $existing_rand_ids) == true);

    return $rand_id;
  }

  /**
   * Get product parameters.
   *
   * @since 2.0.14
   *
   * @param int $product_id Product ID.
   * @param int $product_row_id Product row ID.
   * @param string $order_product_parameters_json Products parameters.
   * @return array of product parameters.
  */
  public static function get_product_parameter_datas($product_id, $product_row_id, $order_product_parameters_json) {
    $model_options = WDFHelper::get_model('options', true);
    $options = $model_options->get_options();
    $decimals = $options->option_show_decimals == 1 ? 2 : 0;
    // get product parameters
    $parameter_rows = array();
    $parameters = WDFJson::decode(esc_attr(get_post_meta($product_id, 'wde_parameters', TRUE)));

    if (is_array($parameters)) {
      foreach ($parameters as $param) {
        $term = get_term($param->id, "wde_parameters");
        if (!is_wp_error($term)) {
          $param->name = $term->name;
        }
        if (empty($param->values) == true) {
          $param_to_add = new stdClass();
          $param_to_add->id = $param->id;
          $param_to_add->name = $param->name;
          $param_to_add->type_id = $param->type_id;
          $param_to_add->value = '';
          $param_to_add->value_price = '';
          $parameter_rows[] = $param_to_add;
        }
        else {
          foreach ($param->values as $val) {
            $values = WDFJson::decode($val);
            $param_to_add = new stdClass();
            $param_to_add->id = $param->id;
            $param_to_add->name = $param->name;
            $param_to_add->type_id = $param->type_id;
            $param_to_add->value = $values->value;
            $param_to_add->value_price = $values->price;
            $parameter_rows[] = $param_to_add;
          }
        }
      }
    }

    // order product parameter values map
    $order_product_parameters = WDFJson::decode($order_product_parameters_json);
    $order_product_prameter_values = array();
    if (is_array($order_product_parameters) || is_object($order_product_parameters)) {
      foreach ($order_product_parameters as $parameter_id_product_row_id => $parameter_value) {
        $order_product_prameter_values[$parameter_id_product_row_id] = $parameter_value;
      }
    }
    $row_default_currency = WDFDb::get_row('currencies', '`default` = 1');

    // parameter datas map
    $parameter_datas_map = array();
    foreach ($parameter_rows as $parameter_row) {
      $parameter_id = $parameter_row->id;
      $price_sign = substr($parameter_row->value_price,0,1);	
      $parameter_row->value_price = $price_sign.WDFText::wde_number_format(substr($parameter_row->value_price,1), $decimals);	
      if (isset($parameter_datas_map[$parameter_id])) {
        $parameter_datas_map[$parameter_id]->values[] = array('value' => $parameter_row->value, 'price' => $parameter_row->value_price);
      } else {
        $parameter_data = new stdClass();
        $parameter_data->id = $parameter_row->id;
        $parameter_data->name = $parameter_row->name;
        $parameter_data->type_id = $parameter_row->type_id;
        $parameter_data->values[] = array('value' => $parameter_row->value, 'price' => $parameter_row->value_price);
        if (isset($order_product_prameter_values[$parameter_data->id . '_' . $product_row_id])) {
          $parameter_data->value = $order_product_prameter_values[$parameter_data->id . '_' . $product_row_id];
        }
        elseif (count($parameter_data->values) > 0) {
          $parameter_data->value = $parameter_data->values[0]['value'];
        }
        else {
          $parameter_data->value = '';
        }
        $parameter_datas_map[$parameter_id] = $parameter_data;          
      }
    }

    $parameter_datas = array();
    if (is_array($parameter_datas_map)) {
      foreach ($parameter_datas_map as $parameter_data) {
        // if (count($parameter_data->values) <= 1 && $parameter_data->type_id != 1 && $parameter_data->type_id != 3)  {
          // continue;
        // }
        for ($i = 0; $i < count($parameter_data->values); $i++) {
          $parameter_data->values[$i]['text'] = $parameter_data->values[$i]['value'];
          if ($parameter_data->values[$i]['price'] != '+' && $parameter_data->values[$i]['price'] != '') {
            $price_sign = substr($parameter_data->values[$i]['price'], 0, 1);
            $price = substr($parameter_data->values[$i]['price'],1);
            if (WDFText::wde_number_format($price, $decimals) != WDFText::wde_number_format(0, $decimals)) {
              if ($row_default_currency->sign_position == 1) {
                $parameter_data->values[$i]['text'] = $parameter_data->values[$i]['value'] . ' (' . $price_sign . $price . $row_default_currency->sign . ')';
              }
              else {
                $parameter_data->values[$i]['text'] = $parameter_data->values[$i]['value'] . ' (' . $price_sign . $row_default_currency->sign . $price .  ')';
              }
            }
          }
        }
        $parameter_datas[] = $parameter_data;
      }
    }
    return $parameter_datas;
  }
  ////////////////////////////////////////////////////////////////////////////////////////
  // Listeners                                                                          //
  ////////////////////////////////////////////////////////////////////////////////////////
}