<?php


/**
 * @category  bgerp
 * @package   bgerp
 *
 * @author    Ivelin Dimov <ivelin_pdimov@abv.bg>
 * @copyright 2006 - 2014 Experta OOD
 * @license   GPL 3
 *
 * @since     v 0.1
 */
class bgerp_BaseImporter extends core_Manager
{
    /**
     * Интерфейси, поддържани от този мениджър
     */
    public $interfaces = 'bgerp_ImportIntf';
    
    
    /**
     * Заглавие
     */
    public $title = 'CSV импорт';
    
    /*
     * Имплементация на bgerp_ImportIntf
     */
    
    
    /**
     * Инициализиране драйвъра
     */
    public function init($params = array())
    {
        $this->mvc = $params['mvc'];
    }
    
    
    /**
     * Функция, връщаща полетата в които ще се вкарват данни
     * в мениджъра-дестинация
     * Не връща полетата които са hidden, input=none,enum,key и keylist
     */
    public function getFields()
    {
        $fields = array();
        $Dfields = $this->mvc->selectFields();
        
        foreach ($Dfields as $name => $fld) {
            if ($fld->input != 'none' && $fld->input != 'hidden' &&
                $fld->kind != 'FNC' && !($fld->type instanceof type_Enum) &&
                !($fld->type instanceof type_Key) && !($fld->type instanceof type_Key2) && !($fld->type instanceof type_KeyList)) {
                $fields[$name] = array('caption' => $fld->caption, 'mandatory' => $fld->mandatory);
            }
        }

        $this->mvc->invoke('AfterPrepareImportFields', array(&$fields));
        
        return $fields;
    }
    
    
    /**
     * Импортиране на csv-файл в даден мениджър
     *
     * @param array $rows   - масив с обработени csv данни, получен от Експерта в bgerp_Import
     * @param array $fields - масив с съответстията на колоните от csv-то и
     *                      полетата от модела array[{поле_от_модела}] = {колона_от_csv}
     *
     * @return string $html - съобщение с резултата
     */
    public function import($rows, $fields)
    {
        $html = '';
        $created = $updated = $skipped = $duplicated = 0;
        core_Debug::startTimer('import');
        
        $onExist = Mode::get('onExist');
        
        // Увеличаваме времето, ако е необходимо
        $rCnt = countR($rows);
        $time = ceil($rCnt / 10);
        if ($time > ini_get('max_execution_time')) {
            core_App::setTimeLimit($time);
        }
        
        $oFields = $this->getFields();
        
        $errArr = array();

        foreach ($rows as $row) {
            $rec = new stdClass();
            
            foreach ($fields as $name => $position) {
                if ($position != -1) {
                    $value = $row[$position];
                    if (isset($oFields[$name]['notColumn'])) {
                        $value = $position;
                    }
                    
                    $rec->{$name} = $value;

                    // Ако ще се добавя файл, правим опит да свалим файла и да го добавим
                    if (isset($rec->{$name})) {
                        if ($this->mvc->getFieldType($name, false) instanceof fileman_FileType) {
                            $bucketId = fileman_Buckets::fetchByName('import');
                            $rec->{$name} = fileman_Get::getFile((object) array('url' => $rec->{$name}, 'bucketId' => $bucketId));
                        }
                    }
                }
            }

            // Ако записа е уникален, създаваме нов, ако не е обновяваме стария
            $fieldsUn = array();

            if ($this->mvc->invoke('BeforeImportRec', array(&$rec)) === false) {
                if ($rec->__errStr) {
                    $row['__errStr'] = $rec->__errStr;
                }
                $errArr[] = $row;

                continue ;
            }

            $exRec = null;
            if (!$this->mvc->isUnique($rec, $fieldsUn, $exRec)) {
                $rec->id = $exRec->id;
            }

            if ($rec->id) {
                if ($onExist == 'skip') {
                    $skipped++;
                    continue;
                } elseif ($onExist == 'duplicate') {
                    unset($rec->id);
                    $duplicated++;
                } else {
                    $updated++;
                }
            } else {
                $created++;
            }

            // Ако е ембедър и се обновяват съществуващите записи
            if($this->mvc instanceof embed_Manager){
                if($onExist == 'update'){
                    if(isset($rec->id)){

                        // Да се добавят полетата от базата от драйвера, за да не бъдат забърсани в последствие
                        if($Driver = $this->mvc->getDriver($rec->id)){
                            $exRec = $this->mvc->fetch($rec->id, '*', false);
                            $addFields = $this->mvc->getDriverFields($Driver);
                            foreach ($addFields as $key => $driverField) {
                                $rec->{$key} = $exRec->{$key};
                            }
                        }
                    }
                }
            }

            $this->mvc->save($rec);
        }
        
        // Ако има грешки при импортиране, ги записваме в отделен файл
        if (!empty($errArr)) {
            $nCsv = '';
            foreach ($errArr as $errStr) {
                $nCsv .= ($nCsv) ? "\n" : '';
                $nCsv .= csv_Lib::getCsvLine($errStr, '|', '"');
            }
            
            $fh = fileman::absorbStr($nCsv, 'exportCsv', 'ImportErr.csv');
            
            $errCnt = countR($errArr);
            if ($errCnt == 1) {
                $errCntW = '1 |запис|. |Записан е в|*: ';
            } else {
                $errCntW = $errCnt . ' |записа|. |Записани са в|*: ';
            }
            status_Messages::newStatus('|Грешка в|* ' . $errCntW . fileman::getLinkToSingle($fh), 'warning');
        }
        
        core_Debug::stopTimer('import');
        
        if ($created) {
            $html .= "|Импортирани|* {$created} |нови записа|*.";
        }
        
        foreach (array('Обновени' => $updated, 'Пропуснати' => $skipped, 'Дублирани' => $duplicated) as $verbName => $cnt) {
            if ($cnt) {
                $html .= ($html) ? '<br />' : '';
                $html .= "|{$verbName}|* {$cnt} |съществуващи записа|*.";
            }
        }
        
        if (isDebug()) {
            $html .= ($html) ? '<br />' : '';
            $html .= '|Общо време|*: ' . round(core_Debug::$timers['import']->workingTime, 2);
        }
        
        return $html;
    }
    
    
    /**
     * Драйвъра може да се показва към всички мениджъри
     */
    public function isApplicable($className)
    {
        return !in_array($className, array('price_ListRules', 'cat_BomDetails'));
    }
}
