<?php

class TM_SoldTogether_Model_Cron
{
    const LOCK_NAME = 'tm_soldtogether_cron_generate';

    /**
     * Locker Object
     *
     * @var Mage_Index_Model_Lock
     */
    protected $_lockInstance = null;

    /**
     * Use file
     *
     * @var boolean
     */
    protected $_use_file_lock = false;

    /**
     * Prefix for path key in core_config_data
     *
     * @var string
     */
    protected $_path_prefix = 'tm_soldtogether/cron_process/';

    public function run($schedule)
    {
        if ($this->isLocked()) {
            $this->createNewJob($schedule->getJobCode());
            return $this;
        }

        $this->lock();
        $lastRun = $this->getValue('last_run');
        // if last run was more than 5 hours ago reinit process
        if ( (strtotime($schedule->getScheduledAt()) - strtotime($lastRun)) > (5 * 60 * 60) ) {
            $this->_initProcess();
        }

        $curPage = $this->getValue('cur_page');
        $orderModel = Mage::getModel('soldtogether/order');
        $customerModel = Mage::getModel('soldtogether/customer');
        $ordersProcessed = $orderModel->reindexRelations($curPage);
        $customersProcessed = $customerModel->reindexRelations($curPage);
        if ($ordersProcessed || $customersProcessed) {
            // save data for next cron run
            $this->saveValue('cur_page', $curPage + 1)
                ->saveValue('last_run', $schedule->getScheduledAt());
            $this->createNewJob($schedule->getJobCode());
        } else {
            $this->deleteValue('cur_page');
            $this->deleteValue('last_run');
        }

        $this->unlock();

        return $this;

    }

    public function createNewJob($jobCode)
    {
        $createdAt = time();
        $scheduledAt = $createdAt + 60;
        $newSchedule = Mage::getModel('cron/schedule')
            ->setJobCode($jobCode)
            ->setStatus(Mage_Cron_Model_Schedule::STATUS_PENDING)
            ->setCreatedAt(strftime('%Y-%m-%d %H:%M:%S', $createdAt))
            ->setScheduledAt(strftime('%Y-%m-%d %H:%M', $scheduledAt));
        $newSchedule->save();
        return $this;
    }

    public function getValue($key)
    {
        $path = $this->_path_prefix . $key;
        return Mage::getModel('core/config_data')
                ->load($path, 'path')
                ->getValue();
    }

    public function saveValue($key, $value)
    {
        $path = $this->_path_prefix . $key;
        Mage::getModel('core/config_data')
            ->load($path, 'path')
            ->setValue($value)
            ->setPath($path)
            ->save();
        return $this;
    }

    public function deleteValue($key)
    {
        $path = $this->_path_prefix . $key;
        Mage::getModel('core/config_data')
            ->load($path, 'path')
            ->delete();
        return $this;
    }

    /**
     * Lock process
     *
     * @return TM_SoldTogether_Model_Cron
     */
    public function lock()
    {
        $this->_getLockInstance()->setLock(
                self::LOCK_NAME,
                $this->_use_file_lock
            );
        return $this;
    }

    /**
     * Unlock process
     *
     * @return TM_SoldTogether_Model_Cron
     */
    public function unlock()
    {
        $this->_getLockInstance()->releaseLock(
                self::LOCK_NAME,
                $this->_use_file_lock
            );
        return $this;
    }

    protected function _initProcess()
    {
        Mage::getModel('soldtogether/order')->getResource()->clearTable();
        Mage::getModel('soldtogether/customer')->getResource()->clearTable();
        $this->saveValue('cur_page', 1);
    }

    /**
     * Returns Lock object.
     *
     * @return Mage_Index_Model_Lock|null
     */
    protected function _getLockInstance()
    {
        if (is_null($this->_lockInstance)) {
            if (class_exists('Mage_Index_Model_Lock')) {
                $this->_lockInstance = Mage_Index_Model_Lock::getInstance();
            } else {
                // fallback for Magento less than 1.9.1
                $this->_lockInstance = Mage::getModel('soldtogether/cron_lock');
            }
        }
        return $this->_lockInstance;
    }

    /**
     * Check if process is locked
     *
     * @return bool
     */
    public function isLocked()
    {
        return $this->_getLockInstance()->isLockExists(
                self::LOCK_NAME,
                $this->_use_file_lock
            );
    }

}
