<?php

class CleanupCronJob extends AbstractCronJob
{

    const LIMIT = 500;
    const OFFSET = 0;
    const CLEANUP_CDR = 'CDR';
    const CLEANUP_UCITEM = 'UCItem';
    const CLEANUP_ALERT = 'Alert';
    const ALERT_LIFETIME = 30;

    public $currentServerTimestamp = '';
    public $lifetimeInSec = '';
    public $searchTimestamp = '';
    public $dontRunCleanUp = false;

    public function run()
    {
        $this->currentServerTimestamp = $this->dateTimeToTimestamp(PhonalisaDate::newServerDate());
        $this->deleteModels();
    }

    public function getCronRule()
    {
        return cfg('CLEANUP_CRON_JOB');
    }

    protected function dateTimeToTimestamp($dateTime)
    {
        $result = $dateTime;
        if (!empty($dateTime)) {
            if (strlen($dateTime) === 10) {
                $dateTime = $dateTime . ' 00:00:00';
            }
            $currentDay = PhonalisaDate::convertServerDateTo("Y-m-d 00:00:00", $dateTime);
            $result = (int) PhonalisaDate::convertServerDateTo("U", $currentDay);
        }
        return $result;
    }

    protected function deleteModels()
    {
        if (!$this->deleteCDRModels()) {
            Log::v(CleanupCronJob::CLEANUP_CDR . '-CleanupJob not done! Create SystemJob.', 'CleanupCronJob');
            $this->createDeleteJob(CleanupCronJob::CLEANUP_CDR);
        } else {
            $this->writeLogMsgForCleanUpModel(CleanupCronJob::CLEANUP_CDR);
        }

        $this->searchTimestamp = '';
        if (!$this->deleteCallListModels()) {
            Log::v(CleanupCronJob::CLEANUP_UCITEM . '-CleanupJob not done! Create SystemJob.', 'CleanupCronJob');
            $this->createDeleteJob(CleanupCronJob::CLEANUP_UCITEM);
        } else {
            $this->writeLogMsgForCleanUpModel(CleanupCronJob::CLEANUP_UCITEM);
        }

        $this->searchTimestamp = '';
        if (!$this->deleteAlertModels()) {
            Log::v(CleanupCronJob::CLEANUP_ALERT . '-CleanupJob not done! Create SystemJob.', 'CleanupCronJob');
            $this->createDeleteJob(CleanupCronJob::CLEANUP_ALERT);
        } else {
            $this->writeLogMsgForCleanUpModel(CleanupCronJob::CLEANUP_ALERT);
        }
    }

    protected function writeLogMsgForCleanUpModel($cleanUpModelName)
    {
        if (!$this->dontRunCleanUp) {
            Log::v($cleanUpModelName . '-CleanupJob done!', 'CleanupCronJob');
        } else {
            Log::v($cleanUpModelName . '-CleanupJob not need to run!', 'CleanupCronJob');
        }
        $this->dontRunCleanUp = false;
    }

    protected function getModelSearchQuery($lifetime)
    {
        $dayInSec = 60 * 60 * 24;

        if ($this->searchTimestamp === '') {
            $lifetimeInSec = (int) $lifetime * $dayInSec;
            $this->searchTimestamp = (int) $this->currentServerTimestamp - $lifetimeInSec;
        }

        $currentDate = PhonalisaDate::convertServerDateTo('Y-m-d*', PhonalisaDate::newServerDate($this->currentServerTimestamp, 'U'));
        $searchQuery = $currentDate;
        $rangeDate = $this->currentServerTimestamp;

        while ($rangeDate !== $this->searchTimestamp) {
            $rangeDate = $rangeDate - $dayInSec;
            $searchQuery.='|' . PhonalisaDate::convertServerDateTo('Y-m-d*', PhonalisaDate::newServerDate($rangeDate, 'U'));
        }
        return $searchQuery;
    }

    protected function deleteCDRModels()
    {
        $lifetime = cfg('LIFETIME_CDR');

        if (!isset($lifetime) && $lifetime == '' && !is_numeric($lifetime)) {
            return false;
        }

        if ($lifetime === '0') {
            $this->dontRunCleanUp = true;
            return true;
        }

        $query = $this->getModelSearchQuery($lifetime);
        $searchFor = 'start_timestamp';
        $searchForDESC = $searchFor . ' DESC';
        $offset = CDR::model()->countByAttributes(array($searchFor => $query));
        $models = CDR::model()->find(array(), $searchForDESC, self::LIMIT, $offset);
        return $this->deleteSortedModels($models);
    }

    protected function deleteCallListModels()
    {
        $lifetime = cfg('LIFETIME_CALL_LIST');

        if (isset($lifetime) && $lifetime !== '' && !is_numeric($lifetime)) {
            return false;
        }

        if ($lifetime === '0') {
            $this->dontRunCleanUp = true;
            return true;
        }

        $query = $this->getModelSearchQuery($lifetime);
        $searchFor = 'timestamp';
        $searchForDESC = $searchFor . ' DESC';
        $offset = UCItem::model()->countByAttributes(array($searchFor => $query));
        $models = UCItem::model()->find(array(), $searchForDESC, self::LIMIT, $offset);
        return $this->deleteSortedModels($models);
    }

    protected function deleteAlertModels()
    {
        $lifetime = self::ALERT_LIFETIME;

        $query = $this->getModelSearchQuery($lifetime);
        $searchFor = 'created';
        $searchForDESC = $searchFor . ' DESC';
        $offset = Alert::model()->countByAttributes(array($searchFor => $query));
        $models = Alert::model()->find(array(), $searchForDESC, self::LIMIT, $offset);
        return $this->deleteSortedModels($models);
    }

    protected function deleteSortedModels($models)
    {
        $deleteDone = false;
        if (count($models) === 0) {
            $this->dontRunCleanUp = true;
            return true;
        }

        if (count($models) < self::LIMIT) {
            $deleteDone = true;
        }

        foreach ($models as $model) {
            $model->delete();
        }
        return $deleteDone;
    }

    protected function createDeleteJob($modelName)
    {
        $meta = json_encode(array(
            'limit' => self::LIMIT,
            'offset' => self::OFFSET,
            'model' => $modelName,
            'searchTimestamp' => $this->searchTimestamp,
            'currentServerTimestamp' => $this->currentServerTimestamp
        ));

        $job = new Job();
        $job->type = Job::Cleanup;
        $job->meta = $meta;
        $job->status = Job::Inserted;
        $job->save();
    }

    public function runCleanupByJob($cleanUpJob)
    {
        Log::v('Run CleanUp-SystemJob', 'CleanupCronJob');
        $meta = json_decode($cleanUpJob->meta);

        $this->searchTimestamp = @$meta->searchTimestamp;
        $this->currentServerTimestamp = @$meta->currentServerTimestamp;

        $jobStatus = Job::Running;

        if ($this->searchTimestamp === '' || $this->currentServerTimestamp === '') {
            $jobStatus = Job::Failed;
            $cleanUpJob->errorText = __('CLEANUP_CRON_JOB_FAILED_BECAUSE_OF_TIMESTAMP');
            Log::e('CleanUp-SystemJob failed!', 'CleanupCronJob');
            return $this->updateDeleteJob($cleanUpJob, $jobStatus);
        }

        if ($meta->model == CleanupCronJob::CLEANUP_CDR) {
            if (!$this->deleteCDRModels()) {
                Log::v(CleanupCronJob::CLEANUP_CDR . '-CleanupJob not done! CleanUp-SystemJob is still running.', 'CleanupCronJob');
            } else {
                $jobStatus = Job::Finished;
                Log::v(CleanupCronJob::CLEANUP_CDR . '-CleanUp-SystemJob finished.', 'CleanupCronJob');
            }
        } else if ($meta->model == CleanupCronJob::CLEANUP_UCITEM) {
            if (!$this->deleteCallListModels()) {
                Log::v(CleanupCronJob::CLEANUP_UCITEM . '-CleanupJob not done! CleanUp-SystemJob is still running.', 'CleanupCronJob');
            } else {
                $jobStatus = Job::Finished;
                Log::v(CleanupCronJob::CLEANUP_UCITEM . '-CleanUp-SystemJob finished.', 'CleanupCronJob');
            }
        } else if ($meta->model == CleanupCronJob::CLEANUP_ALERT) {
            if (!$this->deleteAlertModels()) {
                Log::v(CleanupCronJob::CLEANUP_ALERT . '-CleanupJob not done! CleanUp-SystemJob is still running.', 'CleanupCronJob');
            } else {
                $jobStatus = Job::Finished;
                Log::v(CleanupCronJob::CLEANUP_ALERT . '-CleanUp-SystemJob finished.', 'CleanupCronJob');
            }
        } else {
            $jobStatus = Job::Failed;
            $cleanUpJob->errorText = __('CLEANUP_CRON_JOB_FAILED_BECAUSE_OF_NO_MODEL_FOUND  ');
            Log::e("Try to load $meta->model-SystemJob, but can't find CleanupJob", 'CleanupCronJob');
        }
        $this->updateDeleteJob($cleanUpJob, $jobStatus);
    }

    protected function updateDeleteJob($job, $status)
    {
        $job->status = $status;
        $job->save();
    }
}
