<?php

declare(strict_types=1);

/*
 * This file is part of memberfiles bundle.
 *
 * (c) vonRotenberg
 *
 * @license commercial
 */

namespace vonRotenberg\MemberfilesBundle\EventListener\DataContainer;

use Contao\Backend;
use Contao\BackendUser;
use Contao\CoreBundle\ServiceAnnotation\Callback;
use Contao\DataContainer;
use Contao\File;
use Contao\Image;
use Contao\Input;
use Contao\StringUtil;
use Contao\System;
use Contao\Date;
use Contao\Config;
use vonRotenberg\MemberfilesBundle\Model\SecureDownloadsModel;

class MemberSecureDownloadsListener {

    /**
     * @var BackendUser
     */
    protected $User;

    public function __construct()
    {
        $this->User = BackendUser::getInstance();
    }

    /**
     * @Callback(table="tl_member_secureDownloads", target="list.sorting.child_record")
     */
    public function onChildRecordCallback(array $row)
    {
        $objSecFile = \SecureDownloadsModel::findByPk($row['id']);
        $objFile = $objSecFile->getRelated('uuid');

        return '<div class="tl_content_left">' . ($objFile !== null ? $objFile->name : '') . ' <span style="color:#b3b3b3;padding-left:3px">[' . Date::parse(Config::get('datimFormat'), $row['ctime']) . ']</span></div>';
    }

    /**
     * @Callback(table="tl_member_secureDownloads", target="list.operations.edit.button")
     */
    public function onListEditOperationCallback(array $row, ?string $href, string $label, string $title, ?string $icon, string $attributes, string $table, array $rootRecordIds, ?array $childRecordIds, bool $circularReference, ?string $previous, ?string $next, DataContainer $dc)
    {
        if (!$this->User->isAdmin)
        {
            return '';
        }

        $objSecFile = SecureDownloadsModel::findByPk($row['id']);
        $objFile = $objSecFile->getRelated('uuid');
        $title = sprintf($GLOBALS['TL_LANG']['tl_member_secureDownloads']['edit'][1],$objFile->name);

//        $href .= '&amp;id='.$row['id'];
        $href = 'do=files&amp;act=edit&amp;id=' . $objFile->path;

        return '<a href="'.Backend::addToUrl($href,true,['table']).'" title="'.StringUtil::specialchars($title).'">'.Image::getHtml($icon, $label).'</a> ';
    }

    /**
     * @Callback(table="tl_member_secureDownloads", target="list.operations.delete.button")
     */
    public function onListDeleteOperationCallback(array $row, ?string $href, string $label, string $title, ?string $icon, string $attributes, string $table, array $rootRecordIds, ?array $childRecordIds, bool $circularReference, ?string $previous, ?string $next, DataContainer $dc)
    {
        if (!$this->User->isAdmin && !$this->User->hasAccess('tl_member_secureDownloads::ctime','alexf'))
        {
            return '';
        }

        $objSecFile = SecureDownloadsModel::findByPk($row['id']);
        $objFile = $objSecFile->getRelated('uuid');
        $attributes = ' onclick="if(!confirm(\'' . sprintf($GLOBALS['TL_LANG']['MSC']['deleteConfirmFile'],$objFile->name) . '\'))return false;Backend.getScrollOffset()"';
        $title = sprintf($GLOBALS['TL_LANG']['tl_member_secureDownloads']['delete'][1],$objFile->name);

        $href .= '&amp;id='.$row['id'];

        return '<a href="'.Backend::addToUrl($href).'" title="'.StringUtil::specialchars($title).'"'.$attributes.'>'.Image::getHtml($icon, $label).'</a> ';
    }

    /**
     * @Callback(table="tl_member_secureDownloads", target="list.operations.show.button")
     */
    public function onListShowOperationCallback(array $row, ?string $href, string $label, string $title, ?string $icon, string $attributes, string $table, array $rootRecordIds, ?array $childRecordIds, bool $circularReference, ?string $previous, ?string $next, DataContainer $dc)
    {
        if (Input::get('popup'))
        {
            return '';
        }
        else
        {
            $objSecFile = SecureDownloadsModel::findByPk($row['id']);
            $objFile = $objSecFile->getRelated('uuid');
            $title = sprintf($GLOBALS['TL_LANG']['tl_member_secureDownloads']['show'][1],$objFile->name);

            if ($objFile !== null)
            {
                return '<a href="contao/popup.php?src=' . base64_encode($objFile->path) . '" title="'.StringUtil::specialchars($title, false, true).'"'.$attributes.' onclick="Backend.openModalIframe({\'width\':600,\'title\':\''.str_replace("'", "\\'", StringUtil::specialchars($objFile->name, false, true)).'\',\'url\':this.href,\'height\':300});return false">'.Image::getHtml($icon, $label).'</a> ';
            } else {
                return '';
            }
        }
    }

    /**
     * @Callback(table="tl_member_secureDownloads", target="config.ondelete")
     */
    public function onConfigDeleteCallback(DataContainer $dc)
    {
        $objSecFile = SecureDownloadsModel::findByPk($dc->id);
        $objFile = $objSecFile->getRelated('uuid');

        if ($objFile !== null) {
            $File = new File($objFile->path,true);
            $File->delete();
        }
    }

    /**
     * @Callback(table="tl_member_secureDownloads", target="fields.name.load")
     */
    public function onNameLoadCallback($varValue, DataContainer $dc)
    {
        $objSecFile = SecureDownloadsModel::findByPk($dc->id);
        $objFile = $objSecFile->getRelated('uuid');

        if ($objFile !== null) {
            return $objFile->name;
        }

        return null;
    }

    /**
     * @Callback(table="tl_member_secureDownloads", target="fields.name.save")
     */
    public function onNameSaveCallback($varValue, DataContainer $dc)
    {
        $varValue = str_replace('"', '', $varValue);
        $chunks = array_filter(explode('/', $varValue), 'strlen');

        if (count($chunks) < 1)
        {
            return '';
        }

        // Only allow slashes when creating new folders
        if ($dc->value != '__new__' && count($chunks) > 1)
        {
            throw new Exception($GLOBALS['TL_LANG']['ERR']['invalidName']);
        }

        foreach ($chunks as $chunk)
        {
            if (preg_match('/\.$/', $chunk))
            {
                throw new Exception($GLOBALS['TL_LANG']['ERR']['invalidName']);
            }
        }

        // Check the length without the file extension
        if ($dc->activeRecord)
        {
            $intMaxlength = $GLOBALS['TL_DCA'][$dc->table]['fields'][$dc->field]['eval']['maxlength'] ?? null;

            if ($intMaxlength)
            {
                if ($dc->activeRecord->type == 'file')
                {
                    $intMaxlength -= (strlen($dc->activeRecord->extension) + 1);
                }

                foreach ($chunks as $chunk)
                {
                    if (mb_strlen($chunk) > $intMaxlength)
                    {
                        throw new Exception(sprintf($GLOBALS['TL_LANG']['ERR']['maxlength'], $GLOBALS['TL_DCA'][$dc->table]['fields'][$dc->field]['label'][0], $intMaxlength));
                    }
                }
            }
        }

        $objSecFile = SecureDownloadsModel::findByPk($dc->id);
        $objFile = $objSecFile->getRelated('uuid');
        $File = new File($objFile->path,true);

        if (!$File->exists())
        {
            throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['invalidFile'],'1'.$varValue));
        }

        $strDirectory = dirname($objFile->path);
        if (!$File->renameTo($strDirectory.'/'.$varValue))
        {
            throw new \Exception(sprintf($GLOBALS['TL_LANG']['ERR']['invalidFile'],'2'.$varValue));
        }

        if (($objFile = $File->getModel()) !== null) {
            $objSecFile = \SecureDownloadsModel::findByPk($dc->id);

            if ($objSecFile !== null){
                $objSecFile->uuid = $objFile->uuid;
                $objSecFile->save();
            }
        }

        return null;
    }
}