<?php

class SystemOverviewProcessStatus
{

    const NOT_RUNNING = 0;
    const STARTING = 1;
    const RUNNING = 2;

    public static function getHumanReadableStatus($status)
    {
        switch ($status) {
            case self::NOT_RUNNING:
                return __('SYSTEM_OVERVIEW_PROCESS_STATUS_NOT_RUNNING');
            case self::STARTING:
                return __('SYSTEM_OVERVIEW_PROCESS_STATUS_STARTING');
            case self::RUNNING:
                return __('SYSTEM_OVERVIEW_PROCESS_STATUS_RUNNING');
            default:
                return __('SYSTEM_OVERVIEW_PROCESS_STATUS_NOT_FOUND');
        }
    }

    public static function getStatusColor($status)
    {
        switch ($status) {
            case self::NOT_RUNNING:
                return 'important';
            case self::STARTING:
                return 'warning';
            case self::RUNNING:
                return 'success';
            default:
                return 'important';
        }
    }
}

class SystemOverviewProcesses
{

    const REBOOT = 'reboot';
    const SHUTDOWN = 'shutdown';

    public static function getHumanReadableProcess($process)
    {
        switch ($process) {
            case self::REBOOT:
                return __('SYSTEM_OVERVIEW_PROCESS_REBOOT_SYSTEM');
            case self::SHUTDOWN:
                return __('SYSTEM_OVERVIEW_PROCESS_SHUTDOWN_SYSTEM');
            default:
                return '';
        }
    }
}

class SystemOverview extends PhonalisaRecord
{

    public $descr;
    public $value;
    private $systemInfo = null;

    public static function myAttributes()
    {
        return array(
            'descr' => 'descr',
            'value' => 'value',
        );
    }

    /**
     * Returns the static model of the specified AR class.
     * @param string $className active record class name.
     * @return Job the static model class
     */
    public static function model($className = __CLASS__)
    {
        return parent::model($className);
    }

    /**
     * @return string the associated database table name
     */
    public function tableName()
    {
        return 'systemOverview';
    }

    /**
     * @return array validation rules for model attributes.
     */
    public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            // The following rule is used by search().
            // Please remove those attributes that should not be searched.
            array('descr, value', 'safe'),
            array('descr, value', 'safe', 'on' => 'search'),
        );
    }

    /**
     * @return array relational rules.
     */
    public function relations()
    {
        // NOTE: you may need to adjust the relation name and the related
        // class name for the relations automatically generated below.
        return array(
        );
    }

    /**
     * @return array customized attribute labels (name=>label)
     */
    public function attributeLabels()
    {
        return array(
            'descr' => __('SYSTEM_OVERVIEW_DESCRIPTION'),
            'value' => __('SYSTEM_OVERVIEW_VALUE'),
        );
    }

    public function getCurrentSystemLoad()
    {
        $data = array(
            array(
                "id" => 0,
                "descr" => ""
            ),
        );
        return new CArrayDataProvider($data);
    }

    public function getCurrentSystemOverview()
    {
        $data = array();

        $data['phonalisa_version'] = Yii::app()->params->phonalisaVersion . " / " . Yii::app()->params->phonalisaReleaseBranch;
        $data['release_date'] = Yii::app()->params->phonalisaReleaseDate;
        if (Yii::app()->params->phonalisaReleaseBranch === "experimental") {
            $data['release_commit_Id'] = Yii::app()->params->phonalisaReleaseCommitId;
        }
        $data['user_count'] = User::model()->count();
        $data['sip_active_count'] = SipAccounts::model()->countAllByAttributes(array('state' => 'online'));
        $data['gateway_count'] = Gateway::model()->count();
        $data['gateway_active_count'] = Gateway::model()->countAllByAttributes(array('register' => '1', 'state' => 'REGED'));
        $data['current_system_time'] = $this->getCurrentSystemDateTime();

        if (Yii::app()->params->applianceMode) {
            $memInfo = new MemoryInfo();
            if (($used = $memInfo->getHddFreeString(MemoryInfo::MOUNT_POINT_ROOT)) != "") {
                $data['partition_used_root'] = $used;
            }
            if (($used = $memInfo->getHddFreeString(MemoryInfo::MOUNT_POINT_DB)) != "") {
                $data['partition_used_database'] = $used;
            }
            if (($used = $memInfo->getHddFreeString(MemoryInfo::MOUNT_POINT_SD_CARD)) != "") {
                $data['partition_used_sdcard'] = $used;
            }
        }

        $scorelistEntryStatus = ScoreListEntryStatus::model()->findByAttributes(array());

        if (strlen(cfg("CALL_PROTECTION_API_KEY"))) {
            $data['call_protection'] = $scorelistEntryStatus;
        }
        return $data;
    }

    public function getCurrentSystemOverviewDataProvider()
    {
        $data = $this->getCurrentSystemOverview();
        return $this->getSystemOverviewDataProvider($data);
    }

    private function getCurrentSystemDateTime()
    {
        $data = array();
        $user = $sudoUser = app()->user->sudoUserInstance;

        if ($user) {
            $tz = new DateTimeZone($user->timeZone);
            $data = array(
                "dateTimeString" => PhonalisaDate::convertServerDateTo("c", PhonalisaDate::newServerDate(), true),
                "timezoneOffset" => $tz->getOffset(new DateTime()),
                "datePattern" => $user->dateFormat,
                "timePattern" => $user->timeFormat
            );
        }
        return $data;
    }

    protected function getSystemOverviewDataProvider($overviewData)
    {
        $data = array();
        $id = 0;
        foreach ($overviewData as $key => $value) {
            $data[$id]['id'] = $id;
            $data[$id]['descr'] = $key;
            $data[$id]['value'] = $value;
            $id++;
        }

        $dataProvider = new CArrayDataProvider($data, array(
            'pagination' => false
        ));
        return $dataProvider;
    }

    public function getStatisticsOverview()
    {
        $models = Statistic::model()->findAllByAttributes(array("time_range_type" => Statistic::StatisticTimeRangeTypeYear));
        $overviewData = $this->getSystemOverviewStatisticsData($models);
        return $this->getStatisticsOverviewDataProvider($overviewData);
    }

    protected function getSystemOverviewStatisticsData($models)
    {
        $data = array();
        foreach ($models as $model) {
            if ($model->target_type != Statistic::StatisticTargetTypeGroupUser && $model->target_type != Statistic::StatisticTargetTypeQueue) {
                continue;
            }
            if (isset($data[$model->year][$model->target_type]['count']) && $data[$model->year][$model->target_type]['count'] !== '') {
                $data[$model->year][$model->target_type]['count'] = $data[$model->year][$model->target_type]['count'] + $this->getTotalCallCount($model);
            } else {
                $data[$model->year][$model->target_type]['count'] = $this->getTotalCallCount($model);
            }
            krsort($data[$model->year]);
            $data[$model->year][$model->target_type]['year'] = $model->year;
        }
        ksort($data);
        return $data;
    }

    protected function getTotalCallCount($model)
    {
        return (int) $model->counter_success + (int) $model->counter_missed + (int) $model->counter_missed_no_agents + (int) $model->counter_missed_timeout;
    }

    protected function getStatisticsOverviewDataProvider($allOverviewData)
    {
        $data = array();
        $id = 0;
        foreach ($allOverviewData as $year => $overviewData) {
            $data = $this->processStatisticsOverviewData($overviewData, $data, $id, $year);
        }
        $dataProvider = new CArrayDataProvider($data, array(
            'pagination' => false
        ));
        return $dataProvider;
    }

    protected function processStatisticsOverviewData($overviewData, $data, $id, $year)
    {
        foreach ($overviewData as $targetType => $value) {
            $label = 'GROUPS';
            if ($targetType == Statistic::StatisticTargetTypeQueue) {
                $label = 'QUEUE';
            }
            if (empty($data[$id])) {
                $data[$id] = $this->getDefaultStatisticsTemplate();
            }
            $data[$id]['id'] = $id;
            $data[$id]['targetType'] = $targetType;
            $data[$id]['descr'] = $label . '_STATISTICS_YEAR';
            $data[$id][$year] = $value['count'];
            $id++;
        }
        return $data;
    }

    public function getDefaultStatisticsTemplate()
    {
        $date = (int) date('Y');
        $data = array();
        $data['id'] = '';
        $data['targetType'] = '';
        $data['descr'] = '';

        for ($i = $date; $i >= ($date - 7); $i--) {
            $data[$i] = 0;
        }
        return $data;
    }

    public function getApplianceCmds()
    {
        $data = $this->getSystemOverviewApplianceCmds();
        return $this->getSystemOverviewDataProvider($data);
    }

    protected function getSystemOverviewApplianceCmds()
    {
        $data = PhonalisaCtrldConnector::getProcesses();
        $result = array();

        if ($data->processes) {
            foreach ($data->processes as $process) {
                $result[$process->name]['status'] = $process->status;
            }
        }
        return $result;
    }

    public function shutdownRebootCmds()
    {
        $data = array(
            SystemOverviewProcesses::REBOOT => SystemOverviewProcesses::REBOOT,
            SystemOverviewProcesses::SHUTDOWN => SystemOverviewProcesses::SHUTDOWN
        );
        return $this->getSystemOverviewDataProvider($data);
    }

    public function getProcessStatusByKey($process)
    {
        $allProcess = $this->getSystemOverviewApplianceCmds();
        $result = '';

        if (isset($allProcess[$process]['status'])) {
            $result = $allProcess[$process]['status'];
        }
        return $result;
    }

    public function getSystemInfo()
    {
        if (!$this->systemInfo) {
            $systemInfo = new SystemInfo();
            $this->setSystemInfo($systemInfo);
        }
        return $this->systemInfo;
    }

    private function setSystemInfo($systemInfo)
    {
        $this->systemInfo = $systemInfo;
    }

    public function hasCPUThermalInfo()
    {
        if (!app()->params->applianceMode) {
            return false;
        }

        $systemInfo = $this->getSystemInfo();

        $thermalInfo = $systemInfo->getThermalInfo();
        if (!$thermalInfo) {
            return false;
        }

        if (!$thermalInfo->isEnabled()) {
            return false;
        }
        return true;
    }

    public function hasSystemLoadInfo($duration = SystemLoadInfo::ONE_MINUTE)
    {
        if (!app()->params->applianceMode) {
            return false;
        }

        $systemInfo = $this->getSystemInfo();
        if (!$systemInfo) {
            return false;
        }
        $systemLoadInfo = $systemInfo->getSystemLoadInfo();
        if (!$systemLoadInfo) {
            return false;
        }
        if (is_numeric($systemLoadInfo->getSystemLoad($duration))) {
            return true;
        }
        return false;
    }

    public function hasRamInfo()
    {
        if (!app()->params->applianceMode) {
            return false;
        }

        $systemInfo = $this->getSystemInfo();
        $memoryInfo = $systemInfo->getMemoryInfo();

        if (empty((array) $memoryInfo)) {
            return false;
        }

        $ram = $memoryInfo->getRamInfo();
        if (empty((array) $ram)) {
            return false;
        }
        return true;
    }

    public function hasHddInfo($mountPoint = MemoryInfo::MOUNT_POINT_ROOT)
    {
        if (!app()->params->applianceMode) {
            return false;
        }

        $systemInfo = $this->getSystemInfo();
        $memoryInfo = $systemInfo->getMemoryInfo();

        if (empty((array) $memoryInfo)) {
            return false;
        }

        $hdd = $memoryInfo->getHddInfo($mountPoint);
        if (empty((array) $hdd)) {
            return false;
        }

        return true;
    }

    public function getCPUTemperature()
    {
        $systemInfo = $this->getSystemInfo();
        return $systemInfo->getCPUTemperature();
    }

    public function getSystemLoad($duration = SystemLoadInfo::ONE_MINUTE)
    {
        $systemInfo = $this->getSystemInfo();
        return $systemInfo->getSystemLoad($duration);
    }

    public function getFormattedMemValue($mountpoint = null)
    {
        $systemInfo = $this->getSystemInfo();

        $formattedValue = 0;

        if ($systemInfo->getMemTotal($mountpoint) >= 1024) {
            $formattedValue = round(($systemInfo->getMemUsed($mountpoint) / 1024), 2);
        } else {
            $formattedValue = $systemInfo->getMemUsed($mountpoint);
        }
        return $formattedValue;
    }

    public function getMemoryMax($mountPoint = null)
    {
        $max = 0;
        $sysInfo = $this->getSysteminfo();
        if ($sysInfo->getMemTotal($mountPoint) >= 1024) {
            $max = $sysInfo->getMemTotalInGiB($mountPoint);
        } else {
            $max = $sysInfo->getMemTotal($mountPoint);
        }
        return $max;
    }

    public function getMemoryValueSuffix($mountPoint = null)
    {
        $sysInfo = $this->getSysteminfo();

        $valueSuffix = "";

        if ($sysInfo->getMemTotal($mountPoint) >= 1024) {
            $valueSuffix = " GiB";
        } else {
            $valueSuffix = " MiB";
        }
        return $valueSuffix;
    }
}
