<?php
/**
* 2023 Anvanto
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
*
*  @author    Anvanto <anvantoco@gmail.com>
*  @copyright 2023 Anvanto
*  @license   http://opensource.org/licenses/afl-3.0.php  Academic Free License (AFL 3.0)
*/

class anProductVideosGallery extends ObjectModel
{
    /**
     * @var int
     */
    public $id_video;
    /**
     * @var int
     */
    public $id;
    /**
     * @var int
     */
    public $active = 1;
    public $type_video = 1;
    public $title;
    public $video;
    public $preview;
    public $youtube;

    public $relation = 0;
    public $position = 0;

    /**
     * @var array
     */

    public static $definition = [
        'table' => 'an_product_video_gallery',
        'primary' => 'id_video',
        'multilang' => true,
        'fields' => [

            'type_video' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],

            'active' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'],

            'title' => ['type' =>self::TYPE_HTML, 'validate' => 'isString', 'lang' => true ],
            'video' => ['type' =>self::TYPE_STRING, 'lang' => true ],
            'preview' => ['type' =>self::TYPE_STRING],
            'youtube' => ['type' =>self::TYPE_HTML, 'validate' => 'isString', 'lang' => true ],

            'relation' => ['type' =>self::TYPE_INT, 'validate' => 'isUnsignedId'],
            'position' => ['type' =>self::TYPE_INT, 'validate' => 'isUnsignedId'],

        ],
    ];

    public const imgDir = _PS_MODULE_DIR_.'anproductvideogallery/img/';
    public const imgUrl = __PS_BASE_URI__.'modules/anproductvideogallery/img/';
    public const imgNoPreviewUrl = __PS_BASE_URI__.'modules/anproductvideogallery/views/img/nopreview.webp';
    public const modulePath = _MODULE_DIR_.'anproductvideogallery/';

    public function __construct($id = null, $id_lang = null)
    {
        parent::__construct($id, $id_lang);
    }

    public static function saveRelation($idObj)
    {
        $obj = new anProductVideosGallery($idObj);

        switch (Tools::getValue('relation')){
                
            case 1:
                $obj->updateCategoriesProducts(Tools::getValue('id_categories'), $idObj, 1);
                break;
                
            case 2:
                $obj->updateCategoriesProducts(Tools::getValue('productIds'), $idObj, 2);
                break;    

            default:
                $obj->updateCategoriesProducts([], $idObj, 0);
        }
        
        $obj->save();
    }

    public function updateCategoriesProducts($ids = [], $id_video = 0, $type = 0)
    {
        if (!$id_video){
            return false;
        }        
        
        Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute('DELETE FROM `'._DB_PREFIX_.'an_product_video_gallery_relations` WHERE `id_video`='.(int) $id_video.' ');
        
        if (!$ids || count($ids) == 0) {
            $ids[] = 0;
        }
    
        $ids = array_unique($ids);
    
        foreach ($ids as $id) {                        
            $sql = 'INSERT INTO `'._DB_PREFIX_.'an_product_video_gallery_relations`  (`id_video`, `id_type`, `type`) 
            VALUES ("'.(int) $id_video.'", "'.(int) $id.'", "'.(int) $type.'" )';
            Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute($sql);
        }
        
        return true;
    }   
    
    public static function generateFileName($name, $idLang = false)
    {   
        $ext = substr($name, strrpos($name, '.') + 1);
        $ext = Tools::strtolower($ext);

        if ($idLang){
            return md5(uniqid()) . '_' . $idLang . '.' . $ext;
        }
        return md5(uniqid()) . '.'.$ext;
        
    }
    
    public static function uploadFile($idObj)
    {
        $obj = new anProductVideosGallery($idObj);

        $languages = Language::getLanguages(false);
        $isUpdateImage = false;

        $deleteImage = Tools::getValue('delete_video');

        if ($deleteImage && is_array($deleteImage)){
            foreach ($deleteImage as $id){
                @unlink(self::imgDir . $obj->video[$id]);
                $obj->video[$id] = '';
            }
            $isUpdateImage = true;
        }

        foreach ($languages as $lang) {

            if (isset($_FILES['video_'.$lang['id_lang']]) && isset($_FILES['video_'.$lang['id_lang']]['tmp_name'])
                && !empty($_FILES['video_'.$lang['id_lang']]['tmp_name'])) {

                $videoFile = $_FILES['video_'.$lang['id_lang']];      

                $fileName = self::generateFileName($videoFile['name'], $lang['id_lang']);

                if (!move_uploaded_file($_FILES['video_'.$lang['id_lang']]['tmp_name'], self::imgDir . $fileName)) {
                    return $this->displayError($this->trans('An error occurred while attempting to upload the file.', [], 'Admin.Notifications.Error'));
                }
                
                if (isset($obj->video[$lang['id_lang']]) && $obj->video[$lang['id_lang']] !=''){
                    @unlink(self::imgDir . $obj->video[$lang['id_lang']]);
                }
               
                $obj->video[$lang['id_lang']] = $fileName;
                
                
                $isUpdateImage = true;
            }
        }

        if ($isUpdateImage){
            $obj->save();		
        }   
    }

    public static function uploadPreview($idObj)
    {
        $obj = new anProductVideosGallery($idObj);

        if(tools::getValue('preview_del')){ 
            @unlink(self::imgDir. $obj->preview);
            $obj->preview = '';
            $obj->save();
        }

        if (isset($_FILES['previewFile']) && isset($_FILES['previewFile']['tmp_name']) && !empty($_FILES['previewFile']['tmp_name'])) {

            $videoFile = $_FILES['previewFile'];      

            $fileName = self::generateFileName($videoFile['name']);

            if (!move_uploaded_file($_FILES['previewFile']['tmp_name'], self::imgDir .$fileName)) {
                return $this->displayError($this->trans('An error occurred while attempting to upload the file.', [], 'Admin.Notifications.Error'));
            } else {
                @unlink(self::imgDir . $obj->preview);
                $obj->preview = $fileName;
            }

            $obj->save();
        }
    }

    public static function getVideos($id_product)
    {
        $result = self::getVideosByIdProduct($id_product);

        $videos = [];

        foreach ($result as $video){

            $video['previewFileYoutube'] = ''; //self::imgNoPreviewUrl;

            if ($video['preview'] != ''){
                $video['previewFileYoutube'] = self::imgUrl . $video['preview'];
            } 

            if ($video['type_video'] == 1 && $video['preview'] == '' && preg_match('#(?<=v=|v\/|vi=|vi\/|youtu.be\/)[a-zA-Z0-9_-]{11}#', $video['youtube'], $videoId)) {
                $video['previewFileYoutube'] = 'https://img.youtube.com/vi/'.$videoId[0].'/0.jpg';     
            } else {
                $video['video'] = self::imgUrl . $video['video'];
            }

            $videos[] = $video;
        }
        return $videos;
    }

    public static function getVideosByIdProduct($id_product)
    {
        $context = Context::getContext();
        $cats = product::getProductCategories($id_product);

        $sql = '
        SELECT * FROM `' . _DB_PREFIX_ . 'an_product_video_gallery_relations` szwr, `' . _DB_PREFIX_ . 'an_product_video_gallery` sw
        LEFT JOIN `' . _DB_PREFIX_ . 'an_product_video_gallery_lang` sl 
            ON (sw.`id_video` = sl.`id_video`
            AND sl.`id_lang` = ' . (int) $context->language->id . ')
        WHERE sw.`active`=1
            AND ((sw.type_video = 0 AND sl.video <> "" ) OR (sw.type_video = 1 AND sl.youtube <> ""))
            AND sw.`id_video` = szwr.`id_video` AND sw.`relation` = szwr.`type`
            AND ((szwr.`type` = 1 AND szwr.`id_type` IN (' . implode(', ', $cats) . ')   )
                OR (szwr.`type` = 2 AND szwr.`id_type` = '.(int) $id_product.')
                OR (szwr.`type` = 0 AND szwr.`id_type` = 0)
                )
        ';    
        
        if (Shop::isFeatureActive()) {
            $sql .= ' AND sw.`id_video` IN (
                SELECT sa.`id_video`
                FROM `' . _DB_PREFIX_ . 'an_product_video_gallery_shop` sa
                WHERE sa.id_shop IN (' . implode(', ', Shop::getContextListShopID()) . ')
            )';
        }
       
        $sql .= ' GROUP BY sw.`id_video`';
        $sql .= ' ORDER BY sw.`position`';

        $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);

        return $result;
    }


    public static function getProducsByIdVideos($id_video = 0)
    {
        if (!$id_video){
            return [];
        }
        
        $sql = '
        SELECT  *, p.*
        FROM `' . _DB_PREFIX_ . 'an_product_video_gallery_relations` awl
        
        LEFT JOIN `' . _DB_PREFIX_ . 'product` p
            ON (p.`id_product` = awl.`id_type`)
        
        LEFT JOIN `' . _DB_PREFIX_ . 'product_lang` pl
            ON (p.`id_product` = pl.`id_product`
            AND pl.`id_lang` = ' . (int) Context::getContext()->language->id . Shop::addSqlRestrictionOnLang('pl') . ')        
        
        WHERE awl.`id_video` = ' . (int) $id_video . '  AND awl.`type`="2" ';
        
        $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false);

        return Product::getProductsProperties(Context::getContext()->language->id, $result);
    } 

    public static function getRelationCategories($id_video = 0)
    {
        if (!$id_video){
            return [];
        }
        
        $sql = '
        SELECT `id_type`
        FROM `' . _DB_PREFIX_ . 'an_product_video_gallery_relations` awl        
        WHERE awl.`id_video` = ' . (int) $id_video . ' AND awl.`type`="1"  ';
        
        $result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false);
        
        $cats = [];
        if ($result) {
            foreach ($result as $item){
                $cats[] = $item['id_type'];
            }
        }
        
        return $cats;        
    }  

    public function delete()
    {        
        foreach ($this->video as $videoName){
            @unlink(self::imgDir . $videoName);
        }

        @unlink(self::imgDir . $this->preview);

        return parent::delete();
    }	

    public static function validateUpload($file, $typeFile = 'video')
    {
        $maxFileSize = 40000000;

        $types = ['mp4', 'webm'];

        if ($typeFile == 'previewFile') {
            $types = ['gif', 'jpg', 'jpeg', 'jpe', 'png', 'svg', 'webp'];
        }
        

        if ((int) $maxFileSize > 0 && $file['size'] > (int) $maxFileSize) {
            return Context::getContext()->getTranslator()->trans('File is too large (%1$d kB). Maximum allowed: %2$d kB', [$file['size'] / 1024, $maxFileSize / 1024], 'Admin.Notifications.Error');
        }
        
        
        if (!ImageManager::isCorrectImageFileExt($file['name'], $types) || preg_match('/\%00/', $file['name'])) {
            if ($typeFile == 'previewFile') {
                return Context::getContext()->getTranslator()->trans('Image format not recognized, allowed formats are: .gif, .jpg, .jpeg, .jpe, .png, .svg, .webp', [], 'Admin.Notifications.Error');
            } 

            return Context::getContext()->getTranslator()->trans('Video format not recognized, allowed formats are .mp4, .webm', [], 'Admin.Notifications.Error');
        }  
        
        if ($file['error']) {
            return Context::getContext()->getTranslator()->trans('Error while uploading file; please change your server\'s settings. (Error code: %s)', [$file['error']], 'Admin.Notifications.Error');
        }   
        
        return false;
    }
  
}