<?php 
/**
 * @package    Proxim 
 * @author     Dominic Tanui <dominic@codeworldweb.com.dev>
 * @copyright  2019 Proxim
 * @version    1.5.0
 * @since      File available since Release 1.0.0
 */

namespace Proxim;

use Db;
use Proxim\Database\DbQuery;
use Proxim\Configuration;
use Proxim\Cache\Cache;
use Proxim\ObjectModel;
use Proxim\Util\DateUtils;

/**
 * Class Coupon.
 */
class Coupon extends ObjectModel
{
    const START_ID = 14773;

    const PERCENT =           1;
    const AMOUNT =            3;
    const FREE_UNIT =         5;
    const WRITER_CATEGORY =   7;
    const HALF_CUT_DEADLINE = 8;
    const PRICE_PER_PAGE = 9;

	/** @var $id Coupon ID */
    public $id;
    
    /** @var $site_id */
    public $site_id;

    /** @var int coupon_type */
	public $coupon_type = 1;
	
	/** @var string coupon_code */
    public $coupon_code;
    
    /** @var int coupon_value */
    public $coupon_value;
    
    /** @var int writer_category_id */
    public $writer_category_id;

    /** @var int service_type_id */
    public $service_type_id;
	
	/** @var int order_id */
    public $order_id;
    
    /** @var int user_id */
	public $user_id;

	/** @var bool active */
    public $active = 1;
    
	/** @var bool one_time */
    public $one_time = 0;

    /** @var string expiry */
	public $expiry;

	/** @var string date_upd */
	public $date_upd;

	/** @var string date_add */
	public $date_add;
	
	/**
     * @see ObjectModel::$definition
     */
    public static $definition = array(
        'table' => 'coupon',
        'primary' => 'coupon_id',
        'fields' => array(
            'site_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
            'coupon_type' => array('type' => self::TYPE_INT, 'validate' => 'isInt', 'required' => true),
			'coupon_code' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true),
            'coupon_value' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
            'writer_category_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
            'service_type_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
            'order_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
            'user_id' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
			'active' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
			'one_time' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool'),
            'expiry' => array('type' => self::TYPE_DATE, 'validate' => 'isDateOrNull', 'required' => true),
			'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDateOrNull'),
			'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDateOrNull'),
        ),
	);

	public function __construct($id = null)
    {
		parent::__construct($id);
	}

	/**
     * Overriding check if coupon rate is not empty and if coupon with the same iso code already exists.
     * If it's true, coupon is not added.
     *
     * @param bool $autoDate Automatically set `date_upd` and `date_add` columns
     * @param bool $nullValues Whether we want to use NULL values instead of empty quotes values
     *
     * @return bool Indicates whether the Coupon has been successfully added
     */
    public function add($autoDate = true, $nullValues = false)
    {
        $next_coupon_id = Db::getInstance()->getValue('SELECT MAX(`coupon_id`)+1 FROM `' . DB_PREFIX . 'coupon`');
        if (!$next_coupon_id) {
            $next_coupon_id = self::START_ID;
        }

        $this->id = $next_coupon_id;
        $this->force_id = true;

        return Coupon::exists($this->coupon_code) ? false : parent::add($autoDate, $nullValues);
    }
	
	/**
     * Check if a Coupon already exists.
     *
     * @param int|string $coupon_code int for iso code number string for iso code
     *
     * @return bool Indicates whether the Coupon already exists
     */
    public static function exists($coupon_code)
    {
        $idCouponExists = Coupon::getIdByCouponCode($coupon_code);

        if ($idCouponExists) {
            return true;
        } else {
            return false;
        }
    }

	/**
     * Return available coupon.
     *
     * @param bool $active
     * @param bool $siteId
     *
     * @return array Coupons
     */
    public static function getCoupons($active = true, $siteId = true)
    {

        $sql = new DbQuery();
        $sql->select('c.*');
        $sql->from('coupon', 'c');
        if ($siteId) $sql->where('c.site_id = ' . (int) Configuration::get("SITE_ID") );
        if ($active) $sql->where('c.active = 1 AND expiry >  \'' . pSQL(DateUtils::now()) . '\'' );

        $sql->orderBy('c.coupon_id ASC');

        $result = Db::getInstance()->executeS($sql);
        
        return $result;
    }

	/**
     * Get Coupon.
     *
     * @param int $idCoupon Coupon ID
     *
     * @return array|bool|null|object
     */
    public static function getCoupon($idCoupon)
    {
        $sql = new DbQuery();
        $sql->select('c.*');
        $sql->from('coupon', 'c');
        $sql->where('`coupon_id` = ' . (int) $idCoupon);

        return Db::getInstance(PROX_PROX_USE_SQL_SLAVE)->getRow($sql);
    }

	/**
     * Get Coupon ID by Coupon code.
     *
     * @param string $coupon_code Coupon code
     *
     * @return int Coupon ID
     */
    public static function getIdByCouponCode($coupon_code)
    {
        $cacheId = 'Coupon::getIdByCouponCode_' . pSQL($coupon_code);
        if (!Cache::isStored($cacheId)) {
            $query = Coupon::getIdByQuery();
            $query->where('coupon_code = \'' . pSQL($coupon_code) . '\'');

            $result = (int) Db::getInstance(PROX_USE_SQL_SLAVE)->getValue($query->build());
            Cache::store($cacheId, $result);

            return $result;
        }

        return Cache::retrieve($cacheId);
    }

	/**
     * Get Coupon ID query.
     *
     * @param int $idShop Shop ID
     *
     * @return DbQuery
     */
    public static function getIdByQuery()
    {
        $query = new DbQuery();
        $query->select('c.coupon_id');
        $query->from('coupon', 'c');

        return $query;
    }

	/**
     * Get Coupon instance.
     *
     * @param int $id Coupon ID
     *
     * @return Coupon
     */
    public static function getCouponInstance($id)
    {
        if (!isset(self::$coupon[$id])) {
            self::$coupon[(int) ($id)] = new Coupon($id);
        }

        return self::$coupon[(int) ($id)];
    }
}