<?php
namespace EmotionHero\Api;

use EmotionHero\Application as EH;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Silex\Api\ControllerProviderInterface;
use EmotionHero\Models;
use EmotionHero\Server\Websockets;

class InterfaceControllerProvider implements ControllerProviderInterface
{
    /** @var EH */
    protected $_eh;

    public function __construct()
    {
        $this->_eh = EH::getInstance();
    }

    public function connect(Application $app)
    {
        // creates a new controller based on the default route
        $controllers = $app['controllers_factory'];

        // /interface/game/last
        $controllers->get('/games/last', function (Application $app) {


            $http_origin = $_SERVER['HTTP_ORIGIN'] ?? null;
            if ($http_origin == "https://emotionhero.com" || $http_origin == "http://emotionhero.com")
            {  
                header("Access-Control-Allow-Origin: $http_origin");
                // header("Access-Control-Allow-Origin: https://emotionhero.com");
                header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
                header("Access-Control-Allow-Headers: X-PINGOTHER");
                header("Access-Control-Max-Age: 1728000");
            }

            $gameRepo = $this->_eh->getEm()->getRepository(\EmotionHero\Models\Game::class);
            /* @var $hitRepo EmotionHero\Models\HitRepository */
            $hitRepo = $this->_eh->getEm()->getRepository(\EmotionHero\Models\Hit::class);

            $game = $gameRepo->findOneBy([], ['createdAt'=>'DESC']);

            // id
            //  score
            // achievements, level, time, ranking, hits
            // TODO: make this difference on db-level
            $timeToOutput = $game->getCreatedAt()->add(new \DateInterval("PT1H"));
            $output = [
                'id' => $game->getId(),
                'level' => $game->getLevel()->getName(),
                'ranking' => $gameRepo->getPositionForGame($game),
                'score' => $game->getScore(),
                'achievements' => $game->getAchievements()->count(),
                'time' => $timeToOutput->format("Y-m-d H:i:s"),
                'hits' => [],
            ];

            // of one hit is on the same time as another, skip it
            // as it is part of the same target group (which has been
            // taken into account)
            $times = [];

            foreach ($game->getHits() as $hit) {
                $time = $hit->getTarget()->getTime();
                if(in_array($time, $times)) {
                    continue;
                }
                $times[] = $time;

                $targetSet = $hitRepo->getTargetSetForTarget($hit->getTarget());

                $betterHit = $hitRepo->getBetterHit($hit);

                // score, emotions, expressions, points
                $hitOutput = [
                    'id' => $hit->getId(),
                    'score' => $hit->getScore(),
                    'emotions' => [],
                    'expressions' => [],
                    'points' => [],
                ];

                foreach($targetSet as $target) {
                    $hitOutput['emotions'][$target->getEmotion()->getName()]['target_value'] = $target->getScore();
                    $hitOutput['emotions'][$target->getEmotion()->getName()]['player_value'] = $hit->getEmotions()->getEmotionScore($target->getEmotion());
                }

                $expressions = array_keys($hit->getExpressions()::$EXPRESSIONS_2ND_PERSON);
                sort($expressions);
                foreach ($expressions as $expression) {
                    $score = $hit->getExpressions()->getExpressionScore($expression);
                    // if there is no better hit, better score == score
                    $betterScore = $betterHit ? $betterHit->getExpressions()->getExpressionScore($expression) : $score;

                    $hitOutput['expressions'][$expression]['target_value'] = $betterScore;
                    $hitOutput['expressions'][$expression]['player_value'] = $score;
                }

                foreach($hit->getPoints()->getNormalisedPoints() as $i => $point) {
                    $hitOutput['points']['player'][$i] = ['x'=> $point->getX(), 'y' => $point->getY()];
                }

                if(!empty($betterHit)) {
                    foreach($betterHit->getPoints()->getNormalisedPoints() as $i => $point) {
                        $hitOutput['points']['target'][$i] = ['x'=> $point->getX(), 'y' => $point->getY()];
                    }
                }

                $output['hits'][$time] = $hitOutput;
            }

            return $app['serializer']->serialize($output, 'json');
        });

        $controllers->get('/images', function (Application $app) {


            $http_origin = $_SERVER['HTTP_ORIGIN'] ?? null;
            if ($http_origin == "https://emotionhero.com" || $http_origin == "http://emotionhero.com")
            {  
                header("Access-Control-Allow-Origin: $http_origin");
                // header("Access-Control-Allow-Origin: https://emotionhero.com");
                header("Access-Control-Allow-Methods: POST, GET, OPTIONS");
                header("Access-Control-Allow-Headers: X-PINGOTHER");
                header("Access-Control-Max-Age: 1728000");
            }

            $getEmoBlocks = function($emotion, $feature, $steps = 6) {
                $hitRepo = $this->_eh->getEm()->getRepository(Models\Hit::class);
                $blocks = [];
                $position = 1;
                foreach(range(0, 100, 100/($steps-1)) as $i) {
                    /* @var $hitRepo EmotionHero\Models\HitRepository */
                    $hit = $hitRepo->getClosestHitWithImage($emotion, $i);
                    $img = "data:image/x-icon;base64,".$hit->getFeatureImgAsString($feature);
                    $score = $hit->getEmotions()->getEmotionScore($emotion);
                    $percentage = sprintf("%.0f %%",$score);
                    $blocks[$position] = [
                        'hit_id' => $hit->getId(),
                        'img_data' => $img,
                        'percentage' => $percentage,
                    ];
                    $position++;
                }
                return $blocks;
            };

            $features = ['brows' => 6, 'nose' => 5, 'mouth' => 8];

            $output = [];

            foreach($features as $feature => $steps) {
                foreach(Models\Emotions::$EMOTIONS as $emotion) {
                    $output[$feature][$emotion] = $getEmoBlocks(
                        $emotion,
                        $feature == 'mouth' ? 'mouth_left':$feature,
                        $steps
                        );
                }
            }

            return $app['serializer']->serialize($output, 'json');
        });

        // /interface/images
        $controllers->get('/trigger/game', function (Application $app) {
            // trigger update of client:
            try{
                Websockets::triggerUpdate('game');
            }catch(\Throwable $e) {
                return false;
            }
            return true;
        });
        // /interface/images
        $controllers->get('/trigger/images', function (Application $app) {
            // trigger update of client:
            try{
                Websockets::triggerUpdate('images');
            }catch(\Throwable $e) {
                return false;
            }
            return true;
        });

        return $controllers;
    }
}