#!/usr/bin/env python
# coding: utf-8
#
# GISMO: a Generic Information Search with a Mind of its Own

# DIteration parameters
ALPHA = .25  # diffusion attenuation
N_ITER = 4  # Number of round-trip diffusions
D_MAX = 10  # Maximum number of documents
K_MAX = 5  # Maximum number of keywords
S_MAX = 4  # Maximum number of sentences
F_MAX = 6  # Maximum number of features

# Hierarchical clustering parameters
STRETCH = 2  # Stretch factor that determines the coverage/relevance trade-off
C_MAX = 3  # Maximum depth of concepts
P_MAX = 4  # Maximum depth of document partitions

import gzip
import errno
import os
import dill as pickle

from pathlib import Path


class MixInIO:
    """
    Provide basic save/load capacities to other classes.
    """
    def save(self, filename: str, path='.', erase=False, compress=False):
        """
        Save instance to file.

        Parameters
        ----------
        filename: str
            The stem of the filename.
        path: str or Path
            The location path.
        erase:
            Should existing file be erased if it exists?
        compress:
            Should gzip compression be used?

        Returns
        -------
        None        >>> class MyValue(MixInIO):
        ...     def __init__(self, v=0):
        ...        self.value = v


        Examples
        ----------
        >>> import tempfile
        >>> v1 = ToyClass(42)
        >>> v2 = ToyClass()
        >>> v2.value
        0
        >>> with tempfile.TemporaryDirectory() as tmpdirname:
        ...     v1.save(filename='myfile', compress=True, path=tmpdirname)
        ...     dir_content = [f.name for f in Path(tmpdirname).glob('*')]
        ...     v2.load(filename='myfile', path=Path(tmpdirname))
        ...     v1.save(filename='myfile', compress=True, path=tmpdirname) # doctest.ELLIPSIS
        File ...myfile.pkl.gz already exists!
        >>> dir_content
        ['myfile.pkl.gz']
        >>> v2.value
        42

        >>> with tempfile.TemporaryDirectory() as tmpdirname:
        ...     v1.save(filename='myfile', path=tmpdirname)
        ...     v1.save(filename='myfile', path=tmpdirname) # doctest.ELLIPSIS
        File ...myfile.pkl already exists!

        >>> v1.value = 51
        >>> with tempfile.TemporaryDirectory() as tmpdirname:
        ...     v1.save(filename='myfile', path=tmpdirname)
        ...     v1.save(filename='myfile', path=tmpdirname, erase=True)
        ...     v2.load(filename='myfile', path=tmpdirname)
        ...     dir_content = [f.name for f in Path(tmpdirname).glob('*')]
        >>> dir_content
        ['myfile.pkl']
        >>> v2.value
        51

        >>> with tempfile.TemporaryDirectory() as tmpdirname:
        ...    v2.load(filename='thisfilenamedoesnotexist') # doctest.ELLIPSIS
        Traceback (most recent call last):
         ...
        FileNotFoundError: [Errno 2] No such file or directory: ...
        """
        if isinstance(path, str):
            path = Path(path)
        destination = path / Path(filename).stem
        if compress:
            destination = destination.with_suffix(".pkl.gz")
            if destination.exists() and not erase:
                print(f"File {destination} already exists!")
            else:
                with gzip.open(destination, "wb") as f:
                    pickle.dump(self, f)
        else:
            destination = destination.with_suffix(".pkl")
            if destination.exists() and not erase:
                print(f"File {destination} already exists!")
            else:
                with open(destination, "wb") as f:
                    pickle.dump(self, f)

    def load(self, filename: str, path='.'):
        """
        Load instance from file.

        Parameters
        ----------
        filename: str
            The stem of the filename.
        path: str or Path
            The location path.

        Returns
        -------
        None
        """
        if isinstance(path, str):
            path = Path(path)
        dest = path / Path(filename).with_suffix(".pkl")
        if dest.exists():
            with open(dest, 'rb') as f:
                self.__dict__.update(pickle.load(f).__dict__)
        else:
            dest = dest.with_suffix('.pkl.gz')
            if dest.exists():
                with gzip.open(dest) as f:
                    self.__dict__.update(pickle.load(f).__dict__)
            else:
                raise FileNotFoundError(
                    errno.ENOENT, os.strerror(errno.ENOENT), dest)


class ToyClass(MixInIO):
    def __init__(self, v=0):
        """
        A minimal class to demonstrate the use of the MixInIO MixIN.

        Parameters
        ----------
        v: object
            A value to store.
        """
        self.value = v


toy_source_text = ['Gizmo is a Mogwaï.',
                   'This is a sentence about Blade.',
                   'This is another sentence about Shadoks.',
                   'This very long sentence, with a lot of stuff about Star Wars inside, makes at some point a side reference to the Gremlins movie by comparing Gizmo and Yoda.',
                   'In chinese folklore, a Mogwaï is a demon.']

toy_source_dict = [{'title': 'First Document', 'content': 'Gizmo is a Mogwaï.'},
                   {'title': 'Second Document', 'content': 'This is a sentence about Blade.'},
                   {'title': 'Third Document', 'content': 'This is another sentence about Shadoks.'},
                   {'title': 'Fourth Document',
                    'content': 'This very long sentence, with a lot of stuff about Star Wars inside, '
                               'makes at some point a side reference to the Gremlins movie by '
                               'comparing Gizmo and Yoda.'},
                   {'title': 'Fifth Document', 'content': 'In chinese folklore, a Mogwaï is a demon.'}]
