<?php


/**
 * Помощен клас-имплементация на интерфейса label_SequenceIntf за класа cat_products_Packagings
 *
 * @category  bgerp
 * @package   planning
 *
 * @author    Ivelin Dimov <ivelin_pdimov@abv.com>
 * @copyright 2006 - 2018 Experta OOD
 * @license   GPL 3
 *
 * @since     v 0.1
 * @see label_SequenceIntf
 *
 */
class cat_interface_PackLabelImpl extends label_ProtoSequencerImpl
{
    /**
     * Връща наименованието на етикета
     *
     * @param int $id
     * @param string $series
     * @return string
     */
    public function getLabelName($id, $series = 'label')
    {
        $rec = $this->class->fetchRec($id);
        $productName = cat_Products::getTitleById($rec->productId);
        $packName = cat_UoM::getShortName($rec->packagingId);
        $labelName = "{$productName} ({$packName})";
        
        return $labelName;
    }


    /**
     * Връща масив с данните за плейсхолдерите
     *
     * @param int|NULL $objId
     * @param string $series
     *
     * @return array
     *               Ключа е името на плейсхолдера и стойностите са обект:
     *               type -> text/picture - тип на данните на плейсхолдъра
     *               len -> (int) - колко символа макс. са дълги данните в този плейсхолдер
     *               readonly -> (boolean) - данните не могат да се променят от потребителя
     *               hidden -> (boolean) - данните не могат да се променят от потребителя
     *               importance -> (int|double) - тежест/важност на плейсхолдера
     *               example -> (string) - примерна стойност
     */
    public function getLabelPlaceholders($objId = null, $series = 'label')
    {
        $placeholders = array();
        $placeholders['JOB'] = (object) array('type' => 'text');
        $placeholders['CODE'] = (object) array('type' => 'text');
        $placeholders['NAME'] = (object) array('type' => 'text');
        $placeholders['DATE'] = (object) array('type' => 'text');
        $placeholders['PREVIEW'] = (object) array('type' => 'picture');
        $placeholders['MEASURE_ID'] = (object) array('type' => 'text');
        $placeholders['QUANTITY'] = (object) array('type' => 'text');
        $placeholders['ORDER'] = (object) array('type' => 'text');
        $placeholders['OTHER'] = (object) array('type' => 'text');
        $placeholders['MATERIAL'] = (object) array('type' => 'text');
        $placeholders['SIZE_UNIT'] = (object) array('type' => 'text');
        $placeholders['SIZE'] = (object) array('type' => 'text');
        $placeholders['CATALOG_PRICE'] = (object) array('type' => 'text');
        $placeholders['CATALOG_CURRENCY'] = (object) array('type' => 'text');
        $placeholders['EAN'] = (object) array('type' => 'text');
        $placeholders['EAN_ROTATED'] = (object) array('type' => 'text');

        if (isset($objId)) {
            // Проверка има ли продуктови параметри, които не могат да се редактират от формата
            $productClassId = cat_Products::getClassId();
            $rec = $this->class->fetch($objId);
            $notEditableParamNames = cat_products_Params::getNotEditableLabelParamNames($productClassId, $rec->productId);

            $labelData = $this->getLabelData($objId, 1, true, null, $series);
            if (isset($labelData[0])) {
                foreach ($labelData[0] as $key => $val) {
                    if (!array_key_exists($key, $placeholders)) {
                        $placeholders[$key] = (object) array('type' => 'text');
                    }
                    $placeholders[$key]->example = $val;

                    if(array_key_exists($key, $notEditableParamNames)){
                        $placeholders[$key]->hidden = true;
                    }
                }
            }
        }

        if(array_key_exists('OTHER', $placeholders)){
            $placeholders['OTHER']->recently = true;
        }

        return $placeholders;
    }
    
    
    /**
     * Помощна ф-я връщаща последното задание за артикула от записа на опаковката
     * 
     * @param mixed $id
     * 
     * @return null|stdClass
     */
    private static function getLastJob($id)
    {
        $rec = cat_products_Packagings::fetchRec($id);
        
        $jQuery = planning_Jobs::getQuery();
        $jQuery->XPR('order', 'int', "(CASE #state WHEN 'active' THEN 1 WHEN 'wakeup' THEN 2 WHEN 'stopped' THEN 3 END)");
        $jQuery->where("#productId = {$rec->productId} AND (#state = 'active' || #state = 'stopped' || #state = 'wakeup')");
        $jQuery->orderBy('#order=ASC,#id=DESC');
        
        return $jQuery->fetch();
    }


    /**
     * Връща масив с всички данни за етикетите
     *
     * @param int  $id
     * @param int  $cnt
     * @param bool $onlyPreview
     * @param stdClass $lRec
     * @param string $series
     *
     * @return array - масив от масив с ключ плейсхолдера и стойността
     */
    public function getLabelData($id, $cnt, $onlyPreview = false, $lRec = null, $series = 'label')
    {
        static $resArr = array();
        $lg = core_Lg::getCurrent();
        
        $key = $id . '|' . $cnt . '|' . $onlyPreview . '|' . $lg;
        
        if (isset($resArr[$key])) {
            
            return $resArr[$key];
        }
        
        expect($rec = cat_products_Packagings::fetchRec($id));
        $pRec = cat_Products::fetch($rec->productId, 'code,measureId');
        $quantity = $rec->quantity;
        
        // Каква е мярката и количеството
        $measureId = $pRec->measureId;
        
        // Кое е последното задание към артикула
        $jRec = self::getLastJob($rec);
        if (is_object($jRec)) {
            $jobCode = mb_strtoupper(planning_Jobs::getHandle($jRec->id));
            if ($lg != 'bg' && isset($jRec->saleId)) {
                $lData = cls::get('sales_Sales')->getLogisticData($jRec->saleId);
                $countryCode = drdata_Countries::fetchField(array("#commonName = '[#1#]'", $lData['toCountry']), 'letterCode2');
                $countryCode .= ' ' . date('m/y');
            }
        }
        
        $code = (!empty($pRec->code)) ? $pRec->code : "Art{$rec->productId}";
        $name = trim(cat_Products::getVerbal($rec->productId, 'name'));
        $date = date('m/y');
        
        // Цена по каталог с ДДС
        if ($catalogPrice = price_ListRules::getPrice(price_ListRules::PRICE_LIST_CATALOG, $rec->productId, $rec->packagingId)) {
            $catalogPrice *= 1 + cat_Products::getVat($rec->productId);
            
            $catalogPrice = round($catalogPrice * $quantity, 2);
            $currencyCode = acc_Periods::getBaseCurrencyCode();
            
            Mode::push('text', 'plain');

            $catalogPriceVerbal = core_Type::getByName('double(decimals=2)')->toVerbal($catalogPrice);
            $catalogPriceVerbal = currency_Currencies::decorate($catalogPriceVerbal, $currencyCode, true);
            if($currencyCode == 'BGN'){
                $rate = currency_CurrencyRates::getRate(dt::today(), 'EUR', 'BGN');
                $priceInEuro = round($catalogPrice, 2) / $rate;
                $catalogPriceEuroVerbal = core_Type::getByName('double(decimals=2)')->toVerbal($priceInEuro);
                $catalogPriceEuroVerbal = currency_Currencies::decorate($catalogPriceEuroVerbal, 'EUR', true);
                $catalogPriceVerbal .= " / " . $catalogPriceEuroVerbal;
            }

            Mode::pop('text', 'plain');
        }

        // Ако мярката е 'хил. бр' и к-то е под 10 да се каства към бройки
        $thousandPcsId = cat_UoM::fetchBySysId('K pcs')->id;
        if($measureId == $thousandPcsId && $quantity < 10){
            $quantity *= 1000;
            $measureId = cat_UoM::fetchBySysId('pcs')->id;
        }
        
        $measureId = cat_UoM::getShortName($measureId);
        
        // Продуктови параметри
        Mode::push('printLabel', true);
        $params = cat_Products::getParams($rec->productId, null, true);
        Mode::pop('printLabel');
        $params = cat_Params::getParamNameArr($params, true);
        
        $additionalFields = array();
        $Driver = cat_Products::getDriver($rec->productId);
        if (is_object($Driver)) {
            $additionalFields = $Driver->getAdditionalLabelData($rec->productId, $this->class);
        }
        
        // Дигане на тайм-лимита
        if($onlyPreview === false){
            core_App::setTimeLimit(round($cnt / 8, 2), false, 100);
        }
        
        $arr = array();
        for ($i = 1; $i <= $cnt; $i++) {
            $res = array('CODE' => $code, 'NAME' => $name, 'DATE' => $date, 'MEASURE_ID' => $measureId, 'QUANTITY' => $quantity);
            if (!empty($catalogPriceVerbal)) {
                $res['CATALOG_PRICE'] = $catalogPriceVerbal;
            }

            if (countR($params)) {
                $res = array_merge($res, $params);
            }
            
            if (isset($jobCode)) {
                $res['JOB'] = $jobCode;
            }
            
            if (!empty($rec->eanCode)) {
                $res['EAN'] = $rec->eanCode;
                $res['EAN_ROTATED'] = $rec->eanCode;
            }
            
            if (is_object($Driver)) {
                if (countR($additionalFields)) {
                    $res = $additionalFields + $res;
                }
            }
            
            if (isset($countryCode) && empty($res['OTHER'])) {
                $res['OTHER'] = $countryCode;
            }
            
            $arr[] = $res;
        }

        $resArr[$key] = $arr;
        
        return $resArr[$key];
    }


    /**
     * Броя на етикетите, които могат да се отпечатат
     *
     * @param int $id
     * @param string $series
     *
     * @return int
     */
    public function getLabelEstimatedCnt($id, $series = 'label')
    {
        $rec = cat_products_Packagings::fetchRec($id);
        
        $jRec = self::getLastJob($rec);
        if (is_object($jRec)) {
            $count = $jRec->quantity / $rec->quantity;
            if($reservePercent = cat_Setup::get('LABEL_RESERVE_COUNT')){
                $count *= (1 + $reservePercent);
            }
            
            return ceil($count);
        }
        
        return null;
    }
}
