"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 15.11.21

"""
import mimetypes
import os

from django.db import models

from konova.models import BaseResource
from konova.settings import INTERVENTION_REVOCATION_DOC_PATH


def generate_document_file_upload_path(instance, filename):
    """ Generates the file upload path for certain document instances

    Documents derived from AbstractDocument need specific upload paths for their related models.

    Args:
        instance (): The document instance
        filename (): The filename

    Returns:

    """
    from compensation.models import CompensationDocument, EcoAccountDocument
    from ema.models import EmaDocument
    from intervention.models import InterventionDocument, RevocationDocument
    from konova.settings import ECO_ACCOUNT_DOC_PATH, EMA_DOC_PATH, \
        COMPENSATION_DOC_PATH, \
        INTERVENTION_DOC_PATH

    # Map document types to paths on the hard drive
    path_map = {
        InterventionDocument: INTERVENTION_DOC_PATH,
        CompensationDocument: COMPENSATION_DOC_PATH,
        EmaDocument: EMA_DOC_PATH,
        RevocationDocument: INTERVENTION_REVOCATION_DOC_PATH,
        EcoAccountDocument: ECO_ACCOUNT_DOC_PATH,
    }
    path = path_map.get(instance.__class__, None)
    if path is None:
        raise NotImplementedError("Unidentified document type: {}".format(instance.__class__))

    # RevocationDocument needs special treatment, since these files need to be stored in a subfolder of the related
    # instance's (Revocation) legaldata interventions folder
    if instance.__class__ is RevocationDocument:
        path = path.format(instance.intervention.id)
    else:
        path = path.format(instance.instance.id)
    return path + filename


class AbstractDocument(BaseResource):
    """
    Documents can be attached to compensation or intervention for uploading legal documents or pictures.
    """
    title = models.CharField(max_length=500, null=True, blank=True)
    date_of_creation = models.DateField()
    file = models.FileField()
    comment = models.TextField()

    _valid_mime_types = {
        mimetypes.types_map[".pdf"],
        mimetypes.types_map[".jpg"],
        mimetypes.types_map[".jpeg"],
        mimetypes.types_map[".png"],
    }
    # _maximum_file_size in MB
    _maximum_file_size = 15

    class Meta:
        abstract = True

    def delete(self, using=None, keep_parents=False):
        """ Custom delete function to remove the real file from the hard drive

        Args:
            using ():
            keep_parents ():

        Returns:

        """
        try:
            os.remove(self.file.file.name)
        except (FileNotFoundError, ValueError):
            # File seems to missing anyway - continue!
            pass
        super().delete(using=using, keep_parents=keep_parents)

    @classmethod
    def is_mime_type_valid(cls, _file: str):
        mime_type = _file.content_type
        return mime_type in cls._valid_mime_types

    @classmethod
    def is_file_size_valid(cls, _file):
        max_size = cls._maximum_file_size * pow(1000, 2)
        return _file.size <= max_size

    def replace_file(self, new_file):
        """ Replaces the old file on the hard drive with the new one

        Args:
            new_file (File): The new file

        Returns:

        """
        try:
            os.remove(self.file.file.name)
        except (FileNotFoundError, ValueError):
            pass
        self.file = new_file
        self.save()
