<?php

/**
 * Copyright Souke (2018)
 *
 * contact@souke.fr
 *
 * Ce logiciel est un programme informatique servant à aider les producteurs
 * à distribuer leur production en circuits courts.
 *
 * Ce logiciel est régi par la licence CeCILL soumise au droit français et
 * respectant les principes de diffusion des logiciels libres. Vous pouvez
 * utiliser, modifier et/ou redistribuer ce programme sous les conditions
 * de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
 * sur le site "http://www.cecill.info".
 *
 * En contrepartie de l'accessibilité au code source et des droits de copie,
 * de modification et de redistribution accordés par cette licence, il n'est
 * offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,
 * seule une responsabilité restreinte pèse sur l'auteur du programme,  le
 * titulaire des droits patrimoniaux et les concédants successifs.
 *
 * A cet égard  l'attention de l'utilisateur est attirée sur les risques
 * associés au chargement,  à l'utilisation,  à la modification et/ou au
 * développement et à la reproduction du logiciel par l'utilisateur étant
 * donné sa spécificité de logiciel libre, qui peut le rendre complexe à
 * manipuler et qui le réserve donc à des développeurs et des professionnels
 * avertis possédant  des  connaissances  informatiques approfondies.  Les
 * utilisateurs sont donc invités à charger  et  tester  l'adéquation  du
 * logiciel à leurs besoins dans des conditions permettant d'assurer la
 * sécurité de leurs systèmes et ou de leurs données et, plus généralement,
 * à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
 *
 * Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
 * pris connaissance de la licence CeCILL, et que vous en avez accepté les
 * termes.
 */

namespace frontend\controllers;

use common\helpers\GlobalParam;
use frontend\forms\OpinionForm;
use frontend\forms\ProducerCodeForm;
use GuzzleHttp\Client;
use Yii;
use frontend\forms\PasswordResetRequestForm;
use frontend\forms\ResetPasswordForm;
use frontend\forms\SignupForm;
use common\forms\ContactForm;
use yii\base\InvalidParamException;
use yii\base\UserException;
use yii\data\ActiveDataProvider;
use yii\helpers\Html;
use yii\web\BadRequestHttpException;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\forms\LoginForm;
use yii\web\NotFoundHttpException;

/**
 * Site controller
 */
class SiteController extends FrontendController
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::class,
                'only' => ['logout', 'signup', 'signup-producer'],
                'rules' => [
                    [
                        'actions' => ['signup'],
                        'allow' => true,
                        'roles' => ['?'],
                    ],
                    [
                        'actions' => ['signup-producer'],
                        'allow' => true,
                    ],
                    [
                        'actions' => ['logout'],
                        'allow' => true,
                        'roles' => ['@'],
                    ],
                ],
                'denyCallback' => function($rule, $action) {
                    return $this->redirect('index');
                }
            ],
            'verbs' => [
                'class' => VerbFilter::class,
                'actions' => [
                    'logout' => ['get'],
                ],
            ],
        ];
    }

    /**
     * @inheritdoc
     */
    public function actions()
    {
        return [
            'captcha' => [
                'class' => 'yii\captcha\CaptchaAction',
                'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
            ],
        ];
    }

    /**
     * Affiche la page d'erreur.
     *
     * @return mixed
     */
    public function actionError()
    {
        $exception = \Yii::$app->errorHandler->exception;

        if ($exception->getMessage() == 'Producteur introuvable'
            || \Yii::$app->getRequest()->getQueryParam('producer_not_found')) {
            return $this->render('error-404-producer', ['exception' => $exception]);
        }

        if ($exception !== null) {
            return $this->render('error', ['exception' => $exception]);
        }
    }

    public function actionIndex()
    {
        $dataProviderProducers = new ActiveDataProvider([
            'query' => $this->getProducerModule()->queryProducersActive('producer.date_creation', 'DESC')->query(),
            'pagination' => [
                'pageSize' => 100,
            ],
        ]);

        return $this->render('index', [
            'dataProviderProducers' => $dataProviderProducers,
            'producersArray' => $this->getProducerModule()->findProducersActive('producer.date_creation', 'DESC')
        ]);
    }

    public function actionIamproducer()
    {
        return $this->render('iamproducer', []);
    }

    public function actionService()
    {
        $paidFeaturesArray = $this->getFeatureModule()->getRepository()->findPaidFeatures();

        return $this->render('service', [
            'producerDemoAccount' => $this->getProducerModule()->findOneProducerDemoAccount(),
            'dataProviderPrices' => $this->getDataProviderPrices(),
            'paidFeaturesArray' => $paidFeaturesArray
        ]);
    }

    public function getDataProviderPrices()
    {
        return new ActiveDataProvider([
            'query' => $this->getProducerPriceRangeModule()->queryProducerPriceRanges()->query(),
            'pagination' => [
                'pageSize' => 100,
            ],
        ]);
    }

    public function actionProducers()
    {
        return $this->render('producer', [
            'maximumNumberProducers' => $this->getSettingModule()->getAdminSettingBag()->get('maximumNumberProducers'),
            'countProducersActive' => $this->getProducerModule()->getRepository()->countCacheProducersActiveWithTurnover()
        ]);
    }

    public function actionAbout()
    {
        $aboutFewNumbers = Yii::$app->cache->getOrSet('about_few_numbers4', function () {
            $producerModule = $this->getProducerModule();
            $pointSaleModule = $this->getPointSaleModule();
            $userModule = $this->getUserModule();
            $orderModule = $this->getOrderModule();

            $countProducersActive = $producerModule->getRepository()->countProducersActiveWithTurnover();
            $timeSavedByProducersAverage = $producerModule->getTimeSavedByProducersAverage();
            $countProducersWithOptionTimeSaved = $producerModule->countProducersWithTimeSaved();
            $countPointSalesActive = $pointSaleModule->countPointSalesActiveLastThreeMonths();
            $countUsersActive = $userModule->countUsersActiveLastThreeMonths();
            $averageOrdersPerDay = $orderModule->countGlobalUserOrdersAverageLastSevenDays();
            $turnoverLastThirtyDays = $orderModule->getRepository()->getTurnoverLastThirtyDays();
            $resultMatomoApiVisitSummary = json_decode(file_get_contents(Yii::$app->parameterBag->get('matomoApiVisitSummaryUrl')));
            $numberVisitsByDay = $resultMatomoApiVisitSummary->nb_uniq_visitors / 30;

            return $this->renderPartial('_about_few_numbers', [
                'countProducersActive' => $countProducersActive,
                'countPointSalesActive' => $countPointSalesActive,
                'countUsersActive' => $countUsersActive,
                'averageOrdersPerDay' => $averageOrdersPerDay,
                'turnoverLastThirtyDays' => $turnoverLastThirtyDays,
                'numberVisitsByDay' => $numberVisitsByDay,
                'timeSavedByProducersAverage' => $timeSavedByProducersAverage,
                'countProducersWithOptionTimeSaved' => $countProducersWithOptionTimeSaved
            ]);
        }, 60 * 60 * 24);

        $producerModule = $this->getProducerModule();

        return $this->render('about', [
            'countProducers' => $producerModule->countProducersActiveWithTurnover(),
            'producersWithTestimonials' => $producerModule->findProducersWithTestimonials(),
            'aboutFewNumbers' => $aboutFewNumbers
        ]);
    }

    /*public function actionSourceCode()
    {
        return $this->render('source_code');
    }*/

    /**
     * Liste les producteurs utilisant la plateforme.
     */
    public function actionAjaxProducers()
    {
        \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
        $producersArray = $this->getProducerModule()->findProducersActive();
        $producersArrayReturn = [];

        foreach($producersArray as $producer) {
            $producersArrayReturn[] = [
                'id' => $producer->id,
                'name' => Html::encode($producer->name),
                'type' => Html::encode($producer->type),
                'address' => Html::encode($producer->postcode.' '.$producer->city),
                'latitude' => $producer->latitude,
                'longitude' => $producer->longitude,
                'link' => $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug])
            ];
        }

        return $producersArrayReturn;
    }

    /**
     * Affiche la page de connexion et traite le formulaire de connexion.
     */
    public function actionLogin()
    {
        if (!\Yii::$app->user->isGuest) {
            return \Yii::$app->getResponse()->redirect(['site/index']);
        }

        $model = new LoginForm();
        if ($model->load(Yii::$app->request->post()) && $model->login()) {
            $returnUrl = \Yii::$app->request->get('return_url');

            if ($returnUrl) {
                return $this->redirect($returnUrl);
            }
            else {
                $userProducerArray = $this->getUserProducerModule()->findUserProducersByUser(GlobalParam::getCurrentUser());
                if ($userProducerArray
                    && is_array($userProducerArray)
                    && count($userProducerArray) == 1) {


                    $urlRedirect = $this->getUrlManagerProducer()
                        ->createAbsoluteUrl([
                            'site/index',
                            'slug_producer' => $userProducerArray[0]->producer->slug
                        ]);

                    return $this->redirect($urlRedirect);
                }
                else {
                    return $this->goBack();
                }
            }
        } else {
            return $this->render('@frontend/views/site/login', [
                'model' => $model,
            ]);
        }
    }

    /**
     * Déconnecte l'utilisateur.
     */
    public function actionLogout()
    {
        \Yii::$app->user->logout();

        $referer = Yii::$app->request->referrer ?: Yii::$app->homeUrl;

        // @TODO : comprendre pourquoi le referer n'est pas complet en ligne (slug producteur + controller/action absents)
        if($referer == 'https://'.Yii::getAlias('@producerSubdomain').'.'.Yii::getAlias('@domainName').'/') {
            return $this->redirect(Yii::$app->homeUrl);
        }

        $authenticatedActions = [
            // frontend
            'user/update',

            // producer
            'order/order',
            'order/history',
            'subscription/index',
            'subscription/form',
            'credit/history',
            'credit/add',
            'newsletter/index'
        ];

        foreach($authenticatedActions as $authenticatedAction) {
            $pos = strpos($referer, $authenticatedAction);
            if($pos !== false) {
                $referer = substr($referer, 0, $pos);
            }
        }

        return $this->redirect($referer);
    }

    /**
     * Affiche la page de contact et traite le formulaire s'il est soumis.
     */
    public function actionContact()
    {
        $model = new ContactForm();
        $messageSent = false;
        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            $model->sendEmailAdmin();
            $messageSent = true;
            $model = new ContactForm();
        }

        return $this->render('contact', [
            'model' => $model,
            'messageSent' => $messageSent,
        ]);
    }

    /**
     * Affiche la page d'inscription et traite son formulaire.
     */
    public function actionSignup(string $type = 'user')
    {
        $sponsorshipFromCode = Yii::$app->request->get('from');
        $sponsorshipProducerFrom = $this->findProducerSponsorshipByCode($sponsorshipFromCode);

        $model = new SignupForm();
        $model->option_user_producer = $type;
        $model->sponsored_by = $sponsorshipProducerFrom ? $sponsorshipProducerFrom->id : false;
        $producerModule = $this->getProducerModule();

        if ($model->load(Yii::$app->request->post())) {
            $user = $model->signup();

            if ($user && Yii::$app->getUser()->login($user)) {
                if ($model->isProducer()) {
                    $this->redirect(['site/signup-confirm']);
                }
                else {
                    $producer = $producerModule->findOneProducerById($model->id_producer);
                    if ($producer) {
                        $this->redirect(['site/signup-confirm', 'idProducerRedirect' => $producer->id]);
                    }
                    else {
                        $this->redirect(['site/index']);
                    }
                }
            }
        }

        // Liste des producteurs disponibles
        $producersArray = $producerModule->populateProducerDropdown();
        $dataProducers = $producersArray['data'];
        $optionsProducers = $producersArray['options'];

        $paidFeaturesArray = $this->getFeatureModule()->getRepository()->findPaidFeatures();

        return $this->render('signup', [
            'model' => $model,
            'sponsorshipProducerFrom' => $sponsorshipProducerFrom,
            'dataProducers' => $dataProducers,
            'dataProviderPrices' => $this->getDataProviderPrices(),
            'paidFeaturesArray' => $paidFeaturesArray,
            'optionsProducers' => $optionsProducers,
        ]);
    }

    public function actionSignupProducer()
    {
        $userCurrent = $this->getUserCurrent();
        $sponsorshipFromCode = Yii::$app->request->get('from');
        $sponsorshipProducerFrom = $this->findProducerSponsorshipByCode($sponsorshipFromCode);
        if(!$userCurrent) {
            // Lien parrainage
            if($sponsorshipFromCode && strlen($sponsorshipFromCode)) {
                $this->redirect(['site/signup', 'from' => $sponsorshipFromCode]);
            }
            else {
                $this->redirect(['site/signup']);
            }
        }

        $model = new SignupForm();
        $model->signup_producer_only = 'producer';
        $model->option_user_producer = 'producer';
        $model->sponsored_by = $sponsorshipProducerFrom ? $sponsorshipProducerFrom->id : false;

        if ($model->load(Yii::$app->request->post())) {
            $user = $model->signup($userCurrent);
            if($user) {
                $this->redirect(['site/signup-confirm']);
            }
        }

        return $this->render('signup_producer', [
            'model' => $model,
            'sponsorshipProducerFrom' => $sponsorshipProducerFrom,
            'dataProviderPrices' => $this->getDataProviderPrices(),
            'paidFeaturesArray' => $this->getFeatureModule()->getRepository()->findPaidFeatures()
        ]);
    }

    public function findProducerSponsorshipByCode($sponsorshipFromCode)
    {
        $sponsorshipProducerFrom = null;
        if($sponsorshipFromCode && strlen($sponsorshipFromCode)) {
            $sponsorshipProducerFrom = $this->getProducerModule()->getRepository()->findOneProducerBySponsorshipCode($sponsorshipFromCode);
        }
        return $sponsorshipProducerFrom;
    }

    public function actionSignupConfirm($idProducerRedirect = null)
    {
        $producerModule = $this->getProducerModule();
        $user = $this->getUserCurrent();
        $producerRedirect = $idProducerRedirect ? $producerModule->findOneProducerById($idProducerRedirect) : null ;

        if(!$user) {
            throw new NotFoundHttpException('Page introuvable');
        }

        return $this->render('signup_confirm', [
            'user' => $user,
            'producerRedirect' => $producerRedirect
        ]);
    }

    /**
     * Affiche la page de demande de nouveau mot de passe.
     * Traitement du formulaire.
     */
    public function actionRequestPasswordReset()
    {
        $model = new PasswordResetRequestForm();

        if ($model->load(Yii::$app->request->post()) && $model->validate()) {
            if ($model->sendEmail()) {
                $this->setFlash('success', 'Un lien vous permettant de réinitialiser votre mot de passe 
                    vient d\'être envoyé sur votre boîte mail.');

                return $this->goHome();
            }
            else {
                $this->setFlash('error', "Désolé, aucun compte associé à cette adresse email n'a été trouvé.");
            }
        }

        return $this->render('requestPasswordResetToken', [
            'model' => $model,
        ]);
    }

    /**
     * Met à jour le mot de passe de l'utilisateur.
     */
    public function actionResetPassword($token)
    {
        try {
            $model = new ResetPasswordForm($token);
        } catch (InvalidParamException $e) {
            throw new BadRequestHttpException($e->getMessage());
        }

        if ($model->load($this->getRequest()->post())
            && $model->validate()
            && $model->resetPassword()) {

            $this->setFlash('success', 'Votre nouveau mot de passe vient d\'être sauvegardé.');

            return $this->goHome();
        }

        return $this->render('resetPassword', [
            'model' => $model,
        ]);
    }

    /**
     * Affiche le formulaire de demande de code pour accéder à certains producteurs.
     */
    public function actionProducerCode(int $id)
    {
        $producerModule = $this->getProducerModule();
        $producer = $producerModule->findOneProducerById($id);

        if (!$producer) {
            throw new \yii\web\HttpException(404, 'Producteur introuvable');
        }

        $producerCodeForm = new ProducerCodeForm();
        $producerCodeForm->id_producer = $id;

        if ($producerCodeForm->load($this->getRequest()->post())
            && $producerCodeForm->validate()) {

            $this->getLogic()->setProducerContext($producer);
            $producerModule->addUser(GlobalParam::getCurrentUser(), $producer);

            $this->redirect($this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));
        }

        return $this->render('producer_code', [
            'producer' => $producer,
            'producerCodeForm' => $producerCodeForm,
        ]);
    }

    /**
     * Affiche la page de connexion / inscription  pour accéder notamment au
     * formulaire de commande des producteurs.
     */
    public function actionProducer(int $id)
    {
        $loginForm = new LoginForm();
        $signupForm = new SignupForm();
        $producerModule = $this->getProducerModule();
        $producer = $producerModule->findOneProducerById($id);
        $this->getLogic()->setProducerContext($producer);
        $loginForm->id_producer = $id;
        $signupForm->id_producer = $id;
        $signupForm->option_user_producer = 'user';
        $returnUrl = $this->getRequest()->get('return_url', $this->getUrlManagerProducer()->createAbsoluteUrl(['site/index', 'slug_producer' => $producer->slug]));

        if (Yii::$app->user->isGuest) {
            if ($loginForm->load($this->getRequest()->post()) && $loginForm->login()) {
                if (!strlen($producer->code)) {
                    $producerModule->addUser(GlobalParam::getCurrentUser(), $producer);
                }

                $this->redirect($returnUrl);
            }

            if ($signupForm->load($this->getRequest()->post())
                && ($user = $signupForm->signup())
                && Yii::$app->user->login($user)) {

                    $this->redirect($returnUrl);
            }
        }
        else {
            $this->redirect($returnUrl);
        }

        return $this->render('producer', [
            'loginForm' => $loginForm,
            'signupForm' => $signupForm,
            'producer' => $producer,
        ]);
    }

    /**
     * Indique à l'utilisateur que l'espace d'un producteur est hors ligne.
     */
    public function actionProducerOffline(int $id)
    {
        return $this->render('producer_offline', [
            'producer' => $this->getProducerModule()->findOneProducerById($id),
        ]);
    }

    public function actionOpinion()
    {
        $opinionFormModel = new OpinionForm();
        $opinionSent = false;
        if ($opinionFormModel->load(Yii::$app->request->post()) && $opinionFormModel->validate()) {
            $this->getOpinionModule()->getManager()
                ->sendOpinionEmailAdmin($opinionFormModel, $this->getUserCurrent());
            $opinionSent = true;
            $opinionFormModel = new OpinionForm();
        }

        return $this->render('opinion', [
            'model' => $opinionFormModel,
            'opinionSent' => $opinionSent
        ]);
    }

    /**
     * Affiche les mentions légales.
     */
    public function actionMentions()
    {
        return $this->render('mentions');
    }

    /**
     * Affiche les conditions générale de service.
     */
    public function actionCgv()
    {
        return $this->render('cgv');
    }

    /**
     * Affiche les précisions concernant l'utilisation de la cagnotte
     */
    public function actionCredit()
    {
        return $this->render('credit');
    }

    public function actionImageProducersLogos()
    {
        $image = @imagecreatetruecolor(1600, 1200);

        // fond en blanc
        $whiteBackground = imagecolorallocate($image, 255, 255, 255);
        imagefill($image,0,0,$whiteBackground);

        // logos des producteurs
        $producerModule = $this->getProducerModule();
        $producersArray = $producerModule->getRepository()->findProducersActive();
        shuffle($producersArray);

        $x = 50;
        $y = 0;
        foreach($producersArray as $producer) {
            if($producer->logo) {
                $logo = null;
                $srcLogo = dirname(__FILE__).'/../../producer/web/uploads/'.$producer->logo;
                $imageType = exif_imagetype($srcLogo);
                if($imageType == IMAGETYPE_PNG) {
                    $logo = imagecreatefrompng($srcLogo);
                    $backgroundBlack = imagecolorallocate($logo , 0, 0, 0);
                    imagecolortransparent($logo, $backgroundBlack);
                }
                elseif($imageType == IMAGETYPE_JPEG) {
                    $logo = imagecreatefromjpeg($srcLogo);
                }

                if($logo) {
                    imagealphablending($logo, false);
                    imagesavealpha($logo, true);

                    list(
                        $sourceImageWidth,
                        $sourceImageHeight
                        ) = getimagesize( $srcLogo);

                    if($sourceImageWidth && $sourceImageHeight) {
                        $targetImageWidth  = 120;
                        $targetImageHeight = 120;

                        $sourceAspectRatio = $sourceImageWidth / $sourceImageHeight;
                        $targetAspectRatio = $targetImageWidth / $targetImageHeight;

                        if ($targetAspectRatio > $sourceAspectRatio) {
                            $targetImageHeight = (int) ($targetImageWidth / $sourceAspectRatio);
                        }
                        else {
                            $targetImageWidth = (int) ($targetImageHeight * $sourceAspectRatio);
                        }

                        $transparency = 0.7;
                        imagefilter($logo, IMG_FILTER_COLORIZE, 0,0,0,127 * $transparency);
                        imagecopyresampled($image, $logo, $x, $y + 60, 0, 0, $targetImageWidth, $targetImageHeight, $sourceImageWidth, $sourceImageHeight);

                        $x += $targetImageWidth + 75;
                        if($x > 1600) {
                            $x = rand(-50, 50);
                            $y += 200;
                        }
                    }
                }
            }
        }

        // noir et blanc
        imagefilter($image, IMG_FILTER_GRAYSCALE);

        // rendu de l'image
        header ('Content-Type: image/png');
        imagepng($image);
        imagedestroy($image);
        die();
    }
}
