<?php
/**
 * core.framework
 *
 * @category   Core
 * @package    Core_Storage
 * @subpackage File
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */

/**
 * @category   Core
 * @package    Core_Storage
 * @subpackage File
 * @copyright  Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license    proprietary
 */
class Core_Storage_File extends Core_File
{
    /**
     * @var string
     */
    protected $_url;

    /**
     * @var string
     */
    protected $_urlPath;

    /**
     * @var string
     */
    protected $_storageName;

    /**
     * @var Core_Storage_Strategy_Interface
     */
    protected $_storage;

    /**
     * Constructor
     *
     * @param string $path
     * @param string $name
     * @param float  $size
     * @param string $type
     * @param string $url
     * @param string $storageName
     */
    public function __construct($path, $name = null, $size = null, $type = null, $url = null, $storageName = null)
    {
        parent::__construct($path, $name, $size, $type);

        $this
            ->setUrl($url)
            ->setStorageName($storageName);
    }

    /**
     * @return Core_Storage_Strategy_Interface
     */
    public function getStorage()
    {
        return $this->_storage;
    }

    /**
     * @param Core_Storage_Strategy_Interface $storage
     *
     * @return \Core_Storage_File
     */
    public function setStorage(Core_Storage_Strategy_Interface $storage)
    {
        $this->_storage = $storage;
        return $this;
    }

    /**
     * Get url to file
     * - i.e. http://www.somedomain.com/repository/images/_variations/a/b/abcd.jpg
     * @return string
     */
    public function getUrl()
    {
        if (null === $this->_url) {
            $storage = $this->getStorage();
            if (null === $storage) {
                throw new InvalidArgumentException("Storage not set, can't get URL!");
            } elseif (null === ($storageUrlRoot = $storage->getUrlRoot())) {
                throw new InvalidArgumentException("Storage URL root not set, can't get URL!");
            } else {
                $this->_url = $storage->createFileUrl($this->getStorageName());
            }
        }
        return $this->_url;
    }

    /**
     * Get Url Path to file
     * - i.e. /repository/images/_variations/a/b/abcd.jpg'
     *
     * @return string
     */
    public function getUrlPath()
    {
        if (null === $this->_urlPath) {
            $storage = $this->getStorage();
            if (null === $storage) {
                throw new InvalidArgumentException("Storage not set, can't get URL!");
            } elseif (null === ($storageUrlRoot = $storage->getUrlRoot())) {
                throw new InvalidArgumentException("Storage URL root not set, can't get URL!");
            } else {
                $this->_url = $storage->createFileUrlPath($this->getStorageName());
            }
        }
        return $this->_url;
    }

    /**
     * Set URL
     *
     * @param string $url
     *
     * @return \Core_Storage_File
     */
    public function setUrl($url)
    {
        $this->_url = $url;
        return $this;
    }

    /**
     * Get storage name which superseeds name while storing file
     *
     * @return type
     */
    public function getStorageName()
    {
        if (null === $this->_storageName) {
            $this->setStorageName($this->getName());
        }
        return $this->_storageName;
    }

    /**
     * Set storage name which superseeds name while storing file
     *
     * @param string $storageName
     *
     * @return \Core_Storage_File
     */
    public function setStorageName($storageName)
    {
        $this->_storageName = $storageName;
        return $this;
    }

    /**
     * Get MIME type
     *
     * @return string File MIME type
     * @throws InvalidArgumentException
     */
    public function getType($mime = null) {

        if (null === $this->_type && $this->_isRemote($this->getPath())) {
            $old_path = $this->getPath();
            $tmp_file = tempnam("/tmp", __CLASS__);

            if (!copy($this->getPath(), $tmp_file)) {
                $msg = sprintf('Could not copy file from %s to %s while getting type', $this->getPath(), $tmp_file);
                throw new InvalidArgumentException($msg);
            }

            // So parent getType can work
            $this->setPath($tmp_file);
        }

        $type = parent::getType($mime);

        if (isset($old_path)) {
            $this->setPath($old_path);
            unlink($tmp_file);
        }

        return $type;
    }

    /**
     * Delete file
     *
     * @return boolean
     * @throws Exception
     */
    public function delete()
    {
        if (unlink($this->getPath())) {
            return true;
        } else {
            $msg = sprintf('Unable to delete file %s', $this->getPath());
            throw new InvalidArgumentException($msg);
        }
    }

    /**
     * Rename
     *
     * @param string $newName
     *
     * @return Core_Storage_File
     * @throws Exception
     */
    public function rename($newName)
    {
        $coreStorage = $this->getStorage();

        if (null === $coreStorage) {
            throw new Exception('Storage not set');
        }

        $file = $coreStorage->rename($this->getPath(), $newName);
        $this
            ->setStorage($file->getStorage())
            ->setPath($file->getPath());

        return $this;
    }

    /**
     * See if the file is stored remotely
     *
     * @return boolean
     */
    protected function _isRemote($path)
    {
        if (strpos($path, '://') !== false) {
            return true;
        } else {
            return false;
        }
    }
}