<?php

class ExportNewCallRecordingsCommand extends CConsoleCommand
{

    protected $dateTime;
    protected $fileName;
    protected $fileSize;
    protected $recordExportCounter = 0;
    protected $directoryPath;
    protected $completeFilePath;
    protected $directoryName = 'phonalisa-callrecordings';
    protected $recordFilePrefix = 'phonalisa-callrecording_';
    protected $recordFileSuffix = '.wav';

    public function run($args)
    {
        try {
            $this->initAutomatedExport($args);
        } catch (Exception $e) {
            throw new Exception($e->getMessage(), $e->getCode());
        }
    }

    protected function initAutomatedExport($args)
    {
        $this->initCommandLineParameters($args);
        $this->exportNewCallRecordings();
        $this->showSummaryTextForExportedFiles();
    }

    protected function initCommandLineParameters($args)
    {
        $params = $this->parseCommandLineParameters($args);
        $this->setDirectoryPath(@$params['-toDir']);
    }

    protected function parseCommandLineParameters($args)
    {
        $params = array();
        foreach ($args as $key => $param) {
            if (strpos($param, '-') === 0 && isset($args[($key + 1)])) {
                $params[$param] = $args[($key + 1)];
            }
        }
        return $params;
    }

    protected function setDirectoryPath($dir)
    {
        if (!isset($dir) || empty($dir)) {
            $archiveName = $this->directoryName;
            $runtimePath = $this->completePathWithSlash(Yii::app()->runtimePath);
            $dir = $runtimePath . $archiveName;
        }
        $this->directoryPath = $this->completePathWithSlash($dir);
    }

    protected function completePathWithSlash($path)
    {
        return rtrim($path, '/') . '/';
    }

    protected function exportNewCallRecordings()
    {
        $limit = 1000;
        $offset = 0;

        $this->createDirectory();
        $this->setDateTimeToLastRecordedFile();

        $foundItem = true;
        while ($items = UCItem::model()->find(array('typ' => UCType::Callrecording), 'timestamp', $limit, $offset)) {
            $foundItem = $this->processItems($items);
            if ($foundItem == false) {
                break;
            }
            $offset += $limit;
        }
    }

    protected function createDirectory()
    {
        $directoryPath = $this->directoryPath;
        if (!is_dir($directoryPath)) {
            mkdir($directoryPath);
        }
    }

    protected function setDateTimeToLastRecordedFile()
    {
        $directoryPath = $this->completePathWithSlash($this->directoryPath);
        $scanDir = scandir($directoryPath);
        rsort($scanDir);

        foreach ($scanDir as $key => $value) {
            if ($this->setDateTimeFromSplitedFileName($scanDir[$key], $value) === true) {
                break;
            }
        }
    }

    protected function setDateTimeFromSplitedFileName($haystack, $value)
    {
        if (stripos($haystack, $this->recordFilePrefix) !== false) {
            $splitedFileName = explode('_', $value);
            if (isset($splitedFileName[1]) && isset($splitedFileName[2])) {
                return $this->setDateTimeIfItIsValidate($splitedFileName);
            }
        }
        return false;
    }

    protected function setDateTimeIfItIsValidate($splitedFileName)
    {
        $date = $splitedFileName[1];
        $time = str_replace('-', ':', $splitedFileName[2]);
        $dateTime = $date . ' ' . $time;
        if ($this->validateDateTime($dateTime)) {
            $this->setDateTime($dateTime);
            return true;
        }
        return false;
    }

    protected function processItems($items)
    {
        foreach ($items as $item) {
            if ($this->validateDateTime($this->dateTime)) {
                $timestamp = PhonalisaDate::convertServerDateTo('U', $this->dateTime);
                $userTimestamp = PhonalisaDate::convertServerDateTo('U', $item->timestamp);
                if ((int) $timestamp < (int) $userTimestamp) {
                    if ($this->processItemOutput($item) == false) {
                        return false;
                    }
                }
            } else {
                if ($this->processItemOutput($item) == false) {
                    return false;
                }
            }
        }
        return true;
    }

    protected function processItemOutput($item)
    {
        $this->setDateTime($item->timestamp);
        $recordFileName = $this->getRecordFileName($item);
        $binaryData = $this->getRecordBinaryData($item);
        $this->setFileName($recordFileName);
        if ($this->checkIfFileExists()) {
            return false;
        }
        $this->exportToDirectory($binaryData);
        return $this->checkIfFileExported();
    }

    protected function setDateTime($dateTime)
    {
        if ($this->validateDateTime($dateTime)) {
            $this->dateTime = $dateTime;
        }
    }

    protected function validateDateTime($dateTime, $format = 'Y-m-d H:i:s')
    {
        $d = DateTime::createFromFormat($format, $dateTime);
        if ($d && $d->format($format) == $dateTime) {
            return true;
        }
        return false;
    }

    protected function getRecordFileName($item)
    {
        $prefix = $this->recordFilePrefix;
        $dateTime = $this->replaceEmptySpaceAndColonInDateTime($this->dateTime);
        $userExtension = $this->getUserExtensionForItem($item);
        $suffix = $this->recordFileSuffix;
        return $prefix . $dateTime . "_" . $userExtension . $suffix;
    }

    protected function replaceEmptySpaceAndColonInDateTime($dateTime)
    {
        $searchArray = array(' ', ':');
        $replaceWithArray = array('_', '-');

        return str_replace($searchArray, $replaceWithArray, $dateTime);
    }

    protected function getUserExtensionForItem($item)
    {
        $userExtension = User::model()->findByPk($item->owner_id);
        if (isset($item->owner_id)) {
            return $userExtension->extension;
        }
    }

    protected function getRecordBinaryData($item)
    {
        $length = 0;
        $data = "";
        $binaryField = "record_data";
        $item->getBinaryField($binaryField, $data, $length);
        $this->setBinaryFileSize($length);
        return $data;
    }

    protected function setBinaryFileSize($fileSize)
    {
        $this->fileSize = $fileSize;
    }

    protected function setFileName($fileName)
    {
        $directoryPath = $this->directoryPath;
        $exportedFileName = $directoryPath . $fileName;

        $this->fileName = $fileName;
        $this->completeFilePath = $exportedFileName;
    }

    protected function checkIfFileExists()
    {
        $fileName = $this->completeFilePath;
        return file_exists($fileName);
    }

    protected function exportToDirectory($binaryData)
    {
        $filename = $this->completeFilePath;
        file_put_contents($filename, $binaryData);
    }

    protected function checkIfFileExported()
    {
        if ($this->checkIfFileExists() && ($this->fileSize == filesize($this->completeFilePath))) {
            $this->increaseCounter();
            return true;
        }
        return false;
    }

    protected function increaseCounter()
    {
        $this->recordExportCounter += 1;
    }

    protected function showSummaryTextForExportedFiles()
    {
        $recordFilesCount = $this->recordExportCounter;
        $lastFileDate = $this->dateTime;

        if (empty($lastFileDate)) {
            echo "No call recordings found!\n";
            return;
        }

        if ($recordFilesCount == 0) {
            echo "No new call recordings found. Last call recording from $lastFileDate!\n";
        } else {
            echo "Exported files: $recordFilesCount.\n";
        }
    }
}
