# -*- coding: utf-8 -*-
"""
    boxel.config
    ~~~~~~~~~~~~~

    This module provides configurations needed for boxelization. Such as yaml
    palette parsing and palette generation and also dimension calculations.
"""

import math
import os
import yaml
import numpy as np
from PIL import Image
from utils.singleton import singleton


@singleton
class Dimensions:
    """Dimensions calculated upon init of object including the number of pixels
        per boxel, the width in boxels of the image and the dims in boxels

    :param pixel_width:
    """
    def __init__(self, **kwargs):
        self.pixel_width = kwargs['pixel_width']

        # determine boxel size -- rows first
        self.pixels_per_box = math.ceil(
                kwargs['img_size'][0]/float(self.pixel_width))
        self.output_dims = [
                self.pixel_width,
                int(math.ceil(kwargs['img_size'][1]/self.pixels_per_box))]


@singleton
class Palette:
    """A palette generated by a YAML file containing containg an array of RGB
        values to be used as the only colors for boxels. Contains the name of
        the palette, an array of colors, the amount of colors and a image with
        only those colors in it for easy conversion of other images to this
        palette.

    :param file: A filepath to palette.yml these should be in the palette
        directory
    """
    def __init__(self, **kwargs):
        self.name, self.colors, self.palette_img = self._load(kwargs['file'])
        self.num_of_colors = len(self.colors)

    def _load(self, filepath):
        """Loads the YAML file with an array of RGB values and generates an
            array of RGB colors, gets the name of the palette and makes an
            Image with the colors in palette.yml

        :param filepath: A filepath to palette.yml these should be in the
            palette directory
        """
        if filepath:
            with open(filepath, 'r') as stream:
                base = os.path.basename(filepath)
                filename = os.path.splitext(base)[0]
                dct = yaml.load(stream)
                palette = np.asarray(dct[filename], dtype=np.uint8)
                fill = (256*3) - (palette.shape[0] * palette.shape[1])
                palette_img = Image.new('P', (50, 50))
                palette_img.putpalette(
                        # We add zeros since it's expecting 256*3 color values
                        np.pad(
                            np.asarray(palette).flatten(), (0, fill),
                            'constant'))
                return filename, palette, palette_img
        else:
            return None, np.asarray([], dtype=np.uint8)
