__all__ = ['imread', 'imsave']

import numpy as np
from six import string_types
from PIL import Image

from ...util import img_as_ubyte, img_as_uint
from .tifffile_plugin import imread as tif_imread, imsave as tif_imsave


def imread(fname, dtype=None, img_num=None, **kwargs):
    """Load an image from file.

    Parameters
    ----------
    fname : str or file
       File name or file-like-object.
    dtype : numpy dtype object or string specifier
       Specifies data type of array elements.
    img_num : int, optional
       Specifies which image to read in a file with multiple images
       (zero-indexed).
    kwargs : keyword pairs, optional
        Addition keyword arguments to pass through (only applicable to Tiff
        files for now,  see `tifffile`'s `imread` function).

    Notes
    -----
    Tiff files are handled by Christophe Golhke's tifffile.py [1]_, and support
    many advanced image types including multi-page and floating point.

    All other files are read using the Python Imaging Libary.
    See PIL docs [2]_ for a list of supported formats.

    References
    ----------
    .. [1] http://www.lfd.uci.edu/~gohlke/code/tifffile.py.html
    .. [2] http://pillow.readthedocs.org/en/latest/handbook/image-file-formats.html

    """
    if hasattr(fname, 'lower') and dtype is None:
        kwargs.setdefault('key', img_num)
        if fname.lower().endswith(('.tiff', '.tif')):
            return tif_imread(fname, **kwargs)

    if isinstance(fname, string_types):
        with open(fname, 'rb') as f:
            im = Image.open(f)
            return pil_to_ndarray(im, dtype=dtype, img_num=img_num)
    else:
        im = Image.open(fname)
        return pil_to_ndarray(im, dtype=dtype, img_num=img_num)


def pil_to_ndarray(im, dtype=None, img_num=None):
    """Import a PIL Image object to an ndarray, in memory.

    Parameters
    ----------
    Refer to ``imread``.

    """
    try:
        # this will raise an IOError if the file is not readable
        im.getdata()[0]
    except IOError as e:
        site = "http://pillow.readthedocs.org/en/latest/installation.html#external-libraries"
        pillow_error_message = str(e)
        error_message = ('Could not load "%s" \n'
                         'Reason: "%s"\n'
                         'Please see documentation at: %s'
                         % (im.filename, pillow_error_message, site))
        raise ValueError(error_message)
    frames = []
    grayscale = None
    i = 0
    while 1:
        try:
            im.seek(i)
        except EOFError:
            break

        frame = im

        if img_num is not None and img_num != i:
            im.getdata()[0]
            i += 1
            continue

        if im.format == 'PNG' and im.mode == 'I' and dtype is None:
            dtype = 'uint16'

        if im.mode == 'P':
            if grayscale is None:
                grayscale = _palette_is_grayscale(im)

            if grayscale:
                frame = im.convert('L')
            else:
                frame = im.convert('RGB')

        elif im.mode == '1':
            frame = im.convert('L')

        elif 'A' in im.mode:
            frame = im.convert('RGBA')

        elif im.mode == 'CMYK':
            frame = im.convert('RGB')

        if im.mode.startswith('I;16'):
            shape = im.size
            dtype = '>u2' if im.mode.endswith('B') else '<u2'
            if 'S' in im.mode:
                dtype = dtype.replace('u', 'i')
            frame = np.fromstring(frame.tobytes(), dtype)
            frame.shape = shape[::-1]

        else:
            frame = np.array(frame, dtype=dtype)

        frames.append(frame)