<?php
// Copyright 1999-2017. Plesk International GmbH. All rights reserved.

namespace Plesk\MigrationLibV8\Common\Backend\Files;

use Plesk\MigrationLibV8\Utils\ArrayUtils;
use Plesk\MigrationLibV8\Utils\FileUtils;

class Progress
{
    const OVERALL_STATUS_FINISHED_ERRORS = 'finished-errors';
    const OVERALL_STATUS_FINISHED_OK = 'finished-ok';
    const OVERALL_STATUS_IN_PROGRESS = 'in-progress';

    const GET_PROGRESS_ATTEMPTS_COUNT = 5;
    const GET_PROGRESS_ATTEMPTS_INTERVAL = 1;

    protected $_progressFilePath;
    protected $_data;

    public function __construct($progressFilePath)
    {
        $this->_progressFilePath = $progressFilePath;

        $this->_data = [];
        for ($i = 0; $i < self::GET_PROGRESS_ATTEMPTS_COUNT; $i++) {
            if (FileUtils::fileExists($this->_progressFilePath)) {
                $this->_data = @json_decode(
                    FileUtils::fileGetContents($this->_progressFilePath), true
                );
                if ($this->_data) {
                    break;
                }
            }
            sleep(self::GET_PROGRESS_ATTEMPTS_INTERVAL);
        }
    }

    /**
     * Cleanup progress file, so it looks like migrator was not started yet.
     *
     * Run this function before scheduling migrator asynchronous operations,
     * so you when retrieving/polling progress, you don't get progress of a previously
     * executed operation.
     */
    public function cleanup()
    {
        if (FileUtils::fileExists($this->_progressFilePath)) {
            unlink($this->_progressFilePath);
        }
    }

    /**
     * Get overall status of command execution, as string. Compare with OVERALL_STATUS_* constants.
     *
     * @return string | null
     */
    public function getOverallStatus()
    {
        return ArrayUtils::getElementDefaultNull($this->_data, 'status');
    }

    /**
     * Get action description that is currently executed for all subscriptions.
     *
     * @return string | null
     */
    public function getOverallAction()
    {
        return ArrayUtils::getElementDefaultNull($this->_data, 'action');
    }

    /**
     * Get overall error message of command execution. This error message could be displayed to customer.
     *
     * @return string | null
     */
    public function getOverallErrorMessage()
    {
        return ArrayUtils::getElementDefaultNull($this->_data, 'error_message');
    }

    /**
     * Get overall error ID of command execution.
     *
     * @return string | null
     */
    public function getOverallErrorId()
    {
        return ArrayUtils::getElementDefaultNull($this->_data, 'error_id');
    }

    /**
     * Whether the command was executed successfully or not.
     *
     * If not - use getOverallErrorMessage function to get details.
     *
     * @return bool
     */
    public function isOverallFinishedOk()
    {
        return $this->getOverallStatus() == self::OVERALL_STATUS_FINISHED_OK;
    }

    /**
     * Whether the command was finished or not.
     *
     * @return bool
     */
    public function isOverallFinished()
    {
        return in_array($this->getOverallStatus(), [
            self::OVERALL_STATUS_FINISHED_OK,
            self::OVERALL_STATUS_FINISHED_ERRORS
        ]);
    }
}
