<?php

/**
 * CGBetterUploads API
 *
 * @package CGBetterUploads
 * @category Module
 * @author  calguy1000 <calguy1000@cmsmadesimple.org>
 * @copyright Copyright 2019 by Robert Campbell
 */

namespace CGBetterUploads;

/**
 * this class represents the information needed to display an upload on frontend web interface.
 * It includes regular upload information, and file info, type info, url and download counts etc.
 *
 * @see Upload
 * @property-read string $guid The upload guid
 * @property-read string $category_guid The category_guid of the category this upload is associated with
 * @property-read string $filename The upload original filename.
 * @property-read string $display_name The upload display name
 * @property-read string $summary Brief text summary of this file
 * @property-read string $description Formatted text details of this file.
 * @property-read string $author The author's name
 * @property-read int $created The unix timestamp when this record was created.
 * @property-read array $fields An associative array of fields for this upload.  May be null
 * @property-read string $type The type of file (See the filetype class).  This is for display purposes only.
 * @property-read string $icon The URL of the icon that is associated with this files type.
 * @property-read string $thumbnail_url The URL to the thumbnail associated with this file, if any.
 * @property-read string $canonical_url The Canonical URL to this file.
 * @property-read string $file_url The direct URL to the file.  Should never be displayed to the public, but can be used for processing.
 * @property-read int $size  The size of the uploaded file, in bytes.
 * @property-read int $downloads The number of times this file has been downloaded
 */
class DisplayableUpload implements UploadReadInterface
{
    /**
     * @ignore
     */
    private $upload;

    /**
     * @ignore
     */
    private $canonical_url;

    /**
     * @ignore
     */
    private $file_url;

    /**
     * @ignore
     */
    private $filetype;

    /**
     * @ignore
     */
    private $thumbnail_url;

    /**
     * @ignore
     */
    private $fields;

    /**
     * @ignore
     */
    private $mimetype;

    /**
     * @ignore
     */
    private $downloads;

    /**
     * Construct a DisplayableUpload given an input array
     *
     * @internal
     * @param array $in
     */
    public function __construct(array $in)
    {
        foreach( $in as $key => $val ) {
            switch( $key ) {
            case 'upload':
                if( !$val instanceof Upload ) throw new \InvalidArgumentException('Invalid upload element in array sent to '.__METHOD__);
                $this->upload = $val;
                break;
            case 'mimetype':
                $this->mimetype = trim($val);
                break;
            case 'fields':
                if( !is_null($val) && !is_array($val) ) throw new \InvalidArgumentException('Invalid fields element in array sent to '.__METHOD__);
                $this->fields = $val;
                break;
            case 'canonical':
            case 'canonical_url':
                if( !is_string($val) || !startswith($val,CMS_ROOT_URL) ) throw new \InvalidArgumentException('Invalid canonical element in array sent to '.__METHOD__);
                $this->canonical_url = $val;
                break;
            case 'file_url':
                if( !is_string($val) || !startswith($val,CMS_ROOT_URL) ) throw new \InvalidArgumentException('Invalid file_url element in array sent to '.__METHOD__);
                $this->file_url = $val;
                break;
            case 'thumbnail_url':
                if( !is_null($val) && (!is_string($val) || !startswith($val,CMS_ROOT_URL)) ) {
                    throw new \InvalidArgumentException('Invalid thumbnail_url element in array sent to '.__METHOD__);
                }
                $this->thumbnail_url = $val;
                break;
            case 'filetype':
                if( !is_null($val) && ! $val instanceof FileType ) {
                    throw new \InvalidArgumentException('Invalid FileType element in array sent to '.__METHOD__);
                }
                $this->filetype = $val;
                break;
            case 'downloads':
                if( !is_null($val) ) $val = (int) $val;
                $this->downloads = $val;
                break;
            }
        }
        // must have an upload, and a file url, and fields may be empty
        if( !$this->upload || !$this->file_url ) throw new \InvalidArgumentException('Invalid data passed to '.__METHOD__);
    }

    /**
     * @ignore
     */
    public function __get(string $key)
    {
        return $this->get($key);
    }

    /**
     * Get a property of this object.
     *
     * @param string $key The name of the property to retrieve
     * @return mixed
     */
    public function get( string $key )
    {
        switch( $key ) {
        case 'guid':
            return $this->upload->guid;
        case 'category_guid':
            return $this->upload->category_guid;
        case 'filename':
            return $this->upload->filename;
        case 'display_name':
            return $this->upload->display_name;
        case 'summary':
            return $this->upload->summary;
        case 'description':
            return $this->upload->description;
        case 'author':
            return $this->upload->author;
        case 'created':
            return $this->upload->created;
        case 'fields':
            return $this->fields;
        case 'type':
            if( $this->filetype ) return $this->filetype->name;
            return;
        case 'icon':
            if( $this->filetype ) return CMS_ROOT_URL.'/'.$this->filetype->icon;
            return;
        case 'thumbnail_url':
            return $this->thumbnail_url;
        case 'canonical_url':
            return $this->canonical_url;
        case 'file_url':
            return $this->file_url;
        case 'size':
            return $this->upload->size;
        case 'mimetype':
            return $this->mimetype;
        case 'downloads':
            return $this->downloads;
        default:
            throw new \LogicException("$key is not a gettable property of ".__CLASS__);
        }
    }

    /**
     * @ignore
     */
    public function __set( string $key, $val )
    {
        throw new \LogicException("$key is not a settable property of ".__CLASS__);
    }

    /**
     * Get the value of a field associated with this upload.
     *
     * @param string $key
     * @return mixed
     */
    public function fieldVal(string $key)
    {
        return $this->upload->fieldVal($key);
    }

    /**
     * Format this object into an array
     *
     * @internal
     * @return array
     */
    public function as_array() : array
    {
        $out = [];
        $out['upload'] = $this->upload;
        $out['canonical_url'] = $this->canonical_url;
        $out['mimetype'] = $this->mimetype;
        $out['fields'] = $this->fields;
        $out['file_url'] = $this->file_url;
        $out['thumbnail_url'] = $this->thumbnail_url;
        $out['filetype'] = $this->filetype;
        $out['downloads'] = $this->downloads;
        return $out;
    }

} // class
