from emus.settings import RETROPIE_WEBRETRO_SYSTEM_MAP
from enum import Enum

from django.conf import settings
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.urls import reverse
from django_extensions.db.models import TimeStampedModel
from django_extensions.db.fields import AutoSlugField
from emus.utils import ChoiceEnum


def get_screenshot_upload_path(instance, filename):
    return f"{instance.game_system.retropie_slug}/screenshots/{filename}"


def get_marquee_upload_path(instance, filename):
    return f"{instance.game_system.retropie_slug}/marquee/{filename}"


def get_video_upload_path(instance, filename):
    return f"{instance.game_system.retropie_slug}/videos/{filename}"


def get_rom_upload_path(instance, filename):
    return f"{instance.game_system.retropie_slug}/{filename}"


class Region(Enum):
    USA = "US"
    EUROPE = "EU"
    JAPAN = "JP"


class BaseModel(TimeStampedModel):
    """A base model for providing name and slugged fields for organizational models"""

    name = models.CharField(max_length=255)
    slug = AutoSlugField(populate_from="name")

    class Meta:
        abstract = True

    def slugify_function(self, content):
        for element in settings.REMOVE_FROM_SLUGS:
            content = content.replace(element, "-")
        return content.lower()

    def __str__(self):
        return self.name


class Genre(BaseModel):
    def get_absolute_url(self):
        return reverse("games:genre_detail", args=[self.slug])


class Publisher(BaseModel):
    def get_absolute_url(self):
        return reverse("games:publisher_detail", args=[self.slug])


class Developer(BaseModel):
    def get_absolute_url(self):
        return reverse("games:developer_detail", args=[self.slug])


class GameSystem(BaseModel):
    retropie_slug = models.CharField(
        blank=True,
        null=True,
        max_length=50,
    )

    @property
    def webretro_core(self):
        return settings.RETROPIE_WEBRETRO_SYSTEM_MAP.get(self.retropie_slug, None)

    def get_absolute_url(self):
        return reverse("games:game_system_detail", args=[self.slug])


class Game(BaseModel):
    class Region(ChoiceEnum):
        US = "USA"
        EU = "Europe"
        JP = "Japan"
        X = "Unknown"

    game_system = models.ForeignKey(
        GameSystem,
        on_delete=models.SET_NULL,
        null=True,
    )
    release_date = models.DateField(
        blank=True,
        null=True,
    )
    developer = models.ForeignKey(
        Developer,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )
    publisher = models.ForeignKey(
        Publisher,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )
    genre = models.ManyToManyField(
        Genre,
    )
    players = models.SmallIntegerField(
        default=1,
    )
    kid_game = models.BooleanField(
        default=False,
    )
    description = models.TextField(
        blank=True,
        null=True,
    )
    rating = models.FloatField(
        blank=True,
        null=True,
        validators=[MaxValueValidator(1), MinValueValidator(0)],
    )
    video = models.FileField(
        blank=True,
        null=True,
        max_length=300,
        upload_to=get_video_upload_path,
    )
    marquee = models.ImageField(
        blank=True,
        null=True,
        max_length=300,
        upload_to=get_marquee_upload_path,
    )
    screenshot = models.ImageField(
        blank=True,
        null=True,
        max_length=300,
        upload_to=get_screenshot_upload_path,
    )
    rom_file = models.FileField(
        blank=True,
        null=True,
        max_length=300,
        upload_to=get_rom_upload_path,
    )
    hack = models.BooleanField(
        default=False,
    )
    hack_version = models.CharField(
        max_length=255,
        blank=True,
        null=True,
    )
    english_patched = models.BooleanField(
        default=False,
    )
    english_patched_version = models.CharField(
        max_length=50,
        blank=True,
        null=True,
    )
    undub = models.BooleanField(
        default=False,
    )
    featured = models.BooleanField(
        default=False,
    )
    region = models.CharField(
        max_length=10,
        choices=Region.choices(),
        blank=True,
        null=True,
    )

    def __str__(self):
        return f"{self.name} for {self.game_system}"

    def get_absolute_url(self):
        return reverse("games:game_detail", args=[self.slug])

    def get_play_url(self):
        if self.game_system.retropie_slug in RETROPIE_WEBRETRO_SYSTEM_MAP.keys():
            return reverse("games:game_play_detail", args=[self.slug])
