from os import path, getcwd
from uuid import uuid1

from PIL import Image

from pycs.observable import ObservableDict


class MediaFile(ObservableDict):
    def __init__(self, obj, parent):
        if 'predictionResults' not in obj.keys():
            obj['predictionResults'] = {}

        super().__init__(obj, parent)

    def __get_file(self, identifier):
        file_directory = path.join(getcwd(), 'projects', self.parent['id'], 'data')
        file_name = identifier + self['extension']

        return file_directory, file_name

    def get_file(self):
        return self.__get_file(self['id'])

    def add_result(self, result, origin='user'):
        result['id'] = str(uuid1())
        result['origin'] = origin

        self['predictionResults'][result['id']] = result

    def remove_result(self, identifier):
        del self['predictionResults'][identifier]

    def remove_pipeline_results(self):
        remove = list(filter(lambda k: self['predictionResults'][k]['origin'] == 'pipeline', self['predictionResults'].keys()))

        for key in remove:
            del self['predictionResults'][key]

    def update_result(self, identifier, result, origin='user'):
        result['id'] = identifier
        result['origin'] = origin

        self['predictionResults'][identifier] = result

    def resize(self, maximum_width):
        # check if resized file already exists
        resized = MediaFile(self, self.parent)
        resized['id'] = self['id'] + '-' + maximum_width

        target_directory, target_name = self.__get_file(resized['id'])
        target_path = path.join(target_directory, target_name)

        if path.exists(target_path):
            return resized

        # load full size image
        current_directory, current_name = self.get_file()
        image = Image.open(path.join(current_directory, current_name))
        image_width, image_height = image.size

        # calculate target height
        maximum_width = int(maximum_width)
        maximum_height = int(maximum_width * image_height / image_width)

        # return self if requested size is larger than the image
        if image_width < maximum_width:
            return self

        # resize image
        resized_image = image.resize((maximum_width, maximum_height))

        # save to file
        resized_image.save(target_path, quality=80)
        return resized