<?php

namespace App\Torrentio\Result;

use App\User\Database\CountryLanguages;
use App\Base\Util\PTN;

class ResultFactory
{
    public static $codecMap = [
        'h264' => 'h264',
        'h265' => 'h265',
        'x264' => 'h264',
        'x265' => 'h265',
        '-' => '-'
    ];

    public static function map(
        string $url,
        string $title,
        string $bingeGroup = "-",
        string $imdbId = "-",
    ) {
        $title = trim(preg_replace('/\s+/', ' ', $title));
        $ptn = (object) new PTN()->parse(self::setFilename($url));
        $result = new TorrentioResult(
            self::trimTitle($title),
            self::setUrl($url),
            self::setFilename($url),
            self::setSize($title),
            self::setSeeders($title),
            self::setProvider($title),
            self::setEpisode($title),
            self::setSeason($ptn),
            $bingeGroup,
            self::setResolution($ptn),
            self::setCodec($ptn),
            self::setQuality($ptn),
            $ptn,
            self::setKey($url),
            self::setEpisodeNumber($ptn),
            self::setLanguages($title),
            self::setLanguageFlags($title),
            false,
            uniqid(),
            $imdbId,
        );

        return $result;
    }

    public static function setFilename(string $url)
    {
        $file = explode("/", urldecode($url));
        return end($file);
    }

    public static function setUrl(string $url): string
    {
        return urldecode($url);
    }

    public static function setSize(string $title): string
    {
        $sizeMatch = [];
        preg_match('/(\d+\.?\d+ )(GB|MB)/', $title, $sizeMatch);
        return $sizeMatch[0] ?? "-";
    }

    private static function setSeeders(string $title): string
    {
        $emoji = \Emoji\detect_emoji($title);
        return intval(
            grapheme_substr($title, $emoji[0]['grapheme_offset'] + 1, $emoji[1]['grapheme_offset'] - $emoji[0]['grapheme_offset'])
        );
    }

    private static function setProvider(string $title): string
    {
        $emoji = \Emoji\detect_emoji($title);
        $provider = trim(
            grapheme_substr($title, $emoji[2]['grapheme_offset'] + 1, strlen($title) - $emoji[1]['grapheme_offset'])
        );
        $providerParts = explode("\n", $provider);
        return $providerParts[0];
    }

    private static function setLanguageFlags(string $title): string
    {
        $emoji = \Emoji\detect_emoji($title);
        $provider = trim(
            grapheme_substr($title, $emoji[2]['grapheme_offset'] + 1, strlen($title) - $emoji[1]['grapheme_offset'])
        );

        $providerParts = explode("\n", $provider);

        if (array_key_exists(1, $providerParts)) {
            return $providerParts[1];
        } else {
            return "&#x1f1fa;&#x1f1f8;";
        }
    }

    public static function setLanguages(string $title): array
    {
        $emoji = \Emoji\detect_emoji($title);
        $flags = array_filter($emoji, function ($emoji) {
            return str_starts_with($emoji['short_name'], 'flag-');
        });

        $languages = array_map(function ($flag) {
            return CountryLanguages::fromCountryCode(strtoupper(substr($flag['short_name'], strlen('flag-'))));
        },
        $flags);

        if (count($languages) > 0) {
            return array_values($languages);
        } else {
            return ["English (US)"];
        }
    }

    public static function setCodec(object $ptn): string
    {
        if (isset($ptn->codec) && array_key_exists($ptn->codec, self::$codecMap)) {
            return self::$codecMap[strtolower($ptn->codec)];
        } elseif (isset($ptn->codec)) {
            return $ptn->codec;
        }

        return "-";
    }

    private static function setEpisode(string $title)
    {
        $value = [];
        preg_match('/[sS]\d\d[eE]\d\d/', $title, $value);
        return array_key_exists(0, $value) ? strtoupper($value[0]) : "n/a";
    }

    public static function setSeason(object $ptn): string
    {
        return $ptn->season ?? "-";
    }

    public static function setBingeGroup(string $bingeGroup): string
    {
        return $bingeGroup;
    }

    public static function setResolution(object $ptn): string
    {
        return $ptn->resolution ?? "-";
    }

    public static function setQuality(object $ptn): string
    {
        return $ptn->quality ?? "-";
    }

    public static function setKey(string $url): string
    {
        return substr(base64_encode($url), strlen($url) - 10);
    }

    public static function setEpisodeNumber(object $ptn): string
    {
        return $ptn->episode ?? "-";
    }

    private static function trimTitle(string $title)
    {
        $emoji = \Emoji\detect_emoji($title);
        return trim(grapheme_substr($title, 0, $emoji[0]['grapheme_offset']));
    }
}
