from django.shortcuts import render
from django.utils.translation import gettext as _
import geo
import mimetypes
from ..models import get_item_type, get_item_by_rel_path, TYPE_AUDIO, TYPE_FOLDER, TYPE_IMAGE, TYPE_OTHER, TYPE_VIDEO
import os
import pygal
from ..queries import search_result_query
import random
import themes
import time

ADDTAG_ENTRY = 'addtag-main'
INFOVIEW_ENTRY = 'infoview-main'
DOWNLOAD_ENTRY = 'download-main'
DOWNLOAD_FLAT_ENTRY = 'download-flat-sub'
DOWNLOAD_STRUCT_ENTRY = 'download-struct-sub'
FAVOURITE_ENTRY = 'favourite-main'
REPEAT_ENTRY = 'repeat-main'
SHUFFLE_ENTRY = 'shuffle-main'


def get_wrapper_class(full_path):
    return {
        TYPE_FOLDER: folder_view,
        TYPE_IMAGE: image_view,
        TYPE_VIDEO: video_view,
        TYPE_AUDIO: audio_view,
        TYPE_OTHER: other_view,
    }.get(get_item_type(full_path), base_view)


def get_wrapper_instance(full_path, request):
    return get_wrapper_class(full_path)(request, full_path)


def random_copy(request, lst):
    shuffle_id = pygal.get_shuffle_id(request)
    #
    rv = lst[:]
    if shuffle_id is not None:
        r = random.Random()
        r.seed(shuffle_id)
        r.shuffle(rv)
    return rv


class base_view(object):
    def __init__(self, request, full_path):
        self.request = request
        self.full_path = full_path
        #
        self.item = get_item_by_rel_path(pygal.get_rel_path(full_path))
        if self.item is None:
            raise LookupError("Error while initialising base_view, but item for %s does not exist." % full_path)
        self.is_item = self.item.type != TYPE_FOLDER
        #
        self.mime_type = mimetypes.types_map.get(os.path.splitext(self.full_path)[1])
        self.template = 'pygal/empty.html'

    @property
    def tags(self):
        return self.item.tag_set.all()

    def may_read(self):
        return self.item.may_read(self.request.user)

    def may_modify(self):
        return self.item.may_modify(self.request.user)

    def context_adaption(self, context):
        context['item'] = self
        context['thumbnail_size'] = pygal.get_thumbnail_size(self.request)
        context['title'] = self.name or ''
        context[context.ACTIONBAR].extend(self.actionbar)

    @property
    def heading(self):
        return '%s' % self.item.name

    @property
    def general_information(self):
        rv = []
        full_path = pygal.get_full_path(self.item.rel_path)
        rv.append({'description': _('Name'), 'data': os.path.basename(full_path), 'url': None})
        rv.append({'description': _('Creation Time'), 'data': self.item.item_data.formatted_datetime, 'url': None})
        rv.append({'description': _('Path'), 'data': os.path.dirname(full_path), 'url': None})
        rv.append({'description': _('Size'), 'data': self.__size_txt__(self.item.item_data.size) + 'B', 'url': None})
        rv.append({'description': _('UID'), 'data': self.item.current_uid(), 'url': None})
        return rv

    def __actionbar__(self):
        b = themes.bar()
        if self.is_item:
            if self.is_my_favourite:
                b.append_entry(
                    FAVOURITE_ENTRY,
                    '',
                    themes.color_icon_url(self.request, 'is_favourite.png'),
                    pygal.url_favourite_unset(self.request, self.item.rel_path),
                    True,
                    False
                )
            else:
                b.append_entry(
                    FAVOURITE_ENTRY,
                    '',
                    themes.color_icon_url(self.request, 'favourite.png'),
                    pygal.url_favourite_set(self.request, self.item.rel_path),
                    True,
                    False
                )
        if pygal.is_infoview(self.request):
            b.append_entry(
                INFOVIEW_ENTRY,
                _('Info'),
                themes.color_icon_url(self.request, 'info.png'),
                pygal.url_infoview(self.request, self.item.rel_path),
                True,
                True
            )
        else:
            b.append_entry(
                INFOVIEW_ENTRY,
                _('Info'),
                themes.color_icon_url(self.request, 'info.png'),
                pygal.url_infoview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP),
                True,
                False
            )
        b.append_entry(
            DOWNLOAD_ENTRY,
            _('Download'),
            themes.color_icon_url(self.request, 'download.png'),
            pygal.url_download(self.request, self.item.rel_path),
            True,
            False
        )
        if type(self) is not folder_view:
            if pygal.is_repeatview(self.request):
                b.append_entry(
                    REPEAT_ENTRY,
                    _('Repeat'),
                    themes.color_icon_url(self.request, 'stop.png'),
                    pygal.url_userview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP),
                    True,
                    True
                )
            else:
                b.append_entry(
                    REPEAT_ENTRY,
                    _('Repeat'),
                    themes.color_icon_url(self.request, 'play.png'),
                    pygal.url_repeatview(self.request, self.item.rel_path),
                    True,
                    False
                )
        if pygal.get_shuffle_id(self.request) is None:
            b.append_entry(
                SHUFFLE_ENTRY,
                _('Shuffle'),
                themes.color_icon_url(self.request, 'shuffle.png'),
                pygal.url_userview(self.request, self.item.rel_path, shuffle=pygal.SHUFFLE_ENABLE, search=pygal.SEARCH_KEEP),
                True,
                False
            )
        else:
            b.append_entry(
                SHUFFLE_ENTRY,
                _('Shuffle'),
                themes.color_icon_url(self.request, 'shuffle.png'),
                pygal.url_userview(self.request, self.item.rel_path, shuffle=pygal.SHUFFLE_DISABLE, search=pygal.SEARCH_KEEP),
                True,
                True
            )
        if self.is_item and self.may_modify():
            b.append_entry(
                ADDTAG_ENTRY,
                _('Add Tag'),
                themes.color_icon_url(self.request, 'edit2.png'),
                pygal.url_addtag(self.request, self.item.rel_path),
                True,
                False
            )
        return b

    @property
    def is_my_favourite(self):
        return self.request.user in self.item.favourite_of.all()

    @property
    def actionbar(self):
        return self.__actionbar__()

    def __tagbar__(self):
        b = themes.bar(self.request)
        i = 0
        for t in self.item.tag_set.all():
            i += 1
            edit_url = pygal.url_tagedit(self.request, t.id) if self.may_modify() else None
            b.append_entry('tag-%d' % i, t.text, themes.color_icon_url(self.request, '%d.png' % (i % 10)), edit_url, True, False)
        return b

    @property
    def tagbar(self):
        return self.__tagbar__()

    @property
    def duration(self):
        return self.item.item_data.duration + 1.5

    @property
    def url_item(self):
        return pygal.url_item(self.request, self.item.rel_path)

    @property
    def url_repeatview(self):
        return pygal.url_repeatview(self.request, self.item.rel_path)

    @property
    def is_repeatview(self):
        return pygal.is_repeatview(self.request)

    @property
    def url_thumbnail(self):
        return pygal.url_thumbnail(self.request, self.item.rel_path)

    @property
    def url_userview(self):
        return pygal.url_userview(self.request, self.item.rel_path, search=pygal.SEARCH_KEEP)

    @property
    def url_webnail(self):
        return pygal.url_webnail(self.request, self.item.rel_path)

    @property
    def name(self):
        return self.item.name

    @property
    def date_txt(self):
        return self.item.item_data.formatted_datetime

    def __size_txt__(self, size):
        unit = {
            0: '',
            1: 'k',
            2: 'M',
            3: 'G',
            4: 'T',
        }
        u = 0
        while u < 4 and size > 1000.:
            u += 1
            size /= 1000.
        if size < 100.:
            return '%.2f %s' % (size, unit.get(u, '?'))
        else:
            return '%.1f %s' % (size, unit.get(u, '?'))

    def __duration_txt__(self, duration):
        if duration >= 3600:
            return time.strftime('%H:%M:%S', time.gmtime(duration))
        else:
            return time.strftime('%M:%S', time.gmtime(duration))

    def __parent__(self):
        if pygal.is_searchview(self.request):
            return query_view(self.request, search_result_query(self.request))
        else:
            return get_wrapper_instance(os.path.dirname(self.full_path), self.request)

    def __nxt_prv__(self, direction):
        if direction not in [-1, 1]:
            raise ValueError("Parameter direction is incorrect: %s" % repr(direction))
        fp_il = random_copy(self.request, self.__parent__().sorted_fullpathlist())
        i = fp_il.index(self.full_path)
        lgt = len(fp_il)
        for i in range(i + direction, i + direction * lgt, direction):
            full_path = fp_il[i % lgt]
            if get_item_type(full_path) != TYPE_FOLDER:
                return get_wrapper_instance(full_path, self.request)
        return self

    @property
    def nxt(self):
        return self.__nxt_prv__(1)

    @property
    def prv(self):
        return self.__nxt_prv__(-1)

    def render(self, context):
        return render(self.request, self.template, context=context)


class query_view(object):
    def __init__(self, request, query):
        self.request = request
        self.query = query
        #
        self.template = 'pygal/overview.html'
        #
        self.__item_list__ = None

    def context_adaption(self, context):
        context['item'] = self
        context['thumbnail_size'] = pygal.get_thumbnail_size(self.request)
        context['title'] = self.name or ''
        context[context.ACTIONBAR].extend(self.actionbar)

    @property
    def name(self):
        if pygal.is_favouriteview(self.request):
            return _('My Favourites')
        elif pygal.is_searchview(self.request):
            return _('Search: "%s"' % pygal.get_search_query(self.request))
        else:
            return '-'

    def __actionbar__(self):
        b = themes.bar()
        if pygal.is_infoview(self.request):
            b.append_entry(
                INFOVIEW_ENTRY,
                _('Info'),
                themes.color_icon_url(self.request, 'info.png'),
                pygal.url_infoview(self.request, ''),
                True,
                True
            )
        else:
            b.append_entry(
                INFOVIEW_ENTRY,
                _('Info'),
                themes.color_icon_url(self.request, 'info.png'),
                pygal.url_infoview(self.request, ''),
                True,
                False
            )
        b.append_entry(
            DOWNLOAD_ENTRY,
            _('Download'),
            themes.color_icon_url(self.request, 'download.png'),
            None,
            True,
            False
        )
        b.append_entry_to_entry(
            DOWNLOAD_ENTRY,
            DOWNLOAD_STRUCT_ENTRY,
            _('Download (Structured)'),
            themes.gray_icon_url(self.request, 'download.png'),
            pygal.url_download(self.request, ''),
            True,
            False
        )
        b.append_entry_to_entry(
            DOWNLOAD_ENTRY,
            DOWNLOAD_FLAT_ENTRY,
            _('Download (Flat)'),
            themes.gray_icon_url(self.request, 'download.png'),
            pygal.url_download(self.request, '', flat=True),
            True,
            False
        )
        if pygal.get_shuffle_id(self.request) is None:
            b.append_entry(
                SHUFFLE_ENTRY,
                _('Shuffle'),
                themes.color_icon_url(self.request, 'shuffle.png'),
                pygal.url_userview(self.request, '', shuffle=pygal.SHUFFLE_ENABLE, search=pygal.SEARCH_KEEP),
                True,
                False
            )
        else:
            b.append_entry(
                SHUFFLE_ENTRY,
                _('Shuffle'),
                themes.color_icon_url(self.request, 'shuffle.png'),
                pygal.url_userview(self.request, '', shuffle=pygal.SHUFFLE_DISABLE, search=pygal.SEARCH_KEEP),
                True,
                True
            )
        return b

    @property
    def actionbar(self):
        return self.__actionbar__()

    def sorted_fullpathlist(self):
        il = []
        for item_model in self.query:
            if item_model.may_read(self.request.user):
                il.append(item_model)
        il.sort(key=lambda entry: entry.sort_string(), reverse=True)
        return [pygal.get_full_path(i.rel_path) for i in il]

    def __init_itemlist__(self):
        if self.__item_list__ is None:
            self.__item_list__ = []
            for full_path in self.sorted_fullpathlist():
                w = get_wrapper_instance(full_path, self.request)
                self.__item_list__.append(w)

    @property
    def item_list(self):
        self.__init_itemlist__()
        return random_copy(self.request, self.__item_list__)

    def render(self, context):
        return render(self.request, self.template, context=context)


class folder_view(base_view):
    def __init__(self, *args, **kwargs):
        base_view.__init__(self, *args, **kwargs)
        #
        self.template = 'pygal/overview.html'
        #
        self.__item_list__ = None

    def __actionbar__(self):
        b = base_view.__actionbar__(self)
        b.append_entry_to_entry(
            DOWNLOAD_ENTRY,
            DOWNLOAD_STRUCT_ENTRY,
            _('Download (Structured)'),
            themes.gray_icon_url(self.request, 'download.png'),
            pygal.url_download(self.request, self.item.rel_path),
            True,
            False
        )
        b.append_entry_to_entry(
            DOWNLOAD_ENTRY,
            DOWNLOAD_FLAT_ENTRY,
            _('Download (Flat)'),
            themes.gray_icon_url(self.request, 'download.png'),
            pygal.url_download(self.request, self.item.rel_path, flat=True),
            True,
            False
        )
        return b

    def sorted_fullpathlist(self):
        return [pygal.get_full_path(i.rel_path) for i in self.item.sorted_itemlist()]

    def __init_fullpathlist__(self):
        if self.__item_list__ is None:
            self.__item_list__ = []
            for full_path in self.sorted_fullpathlist():
                w = get_wrapper_instance(full_path, self.request)
                self.__item_list__.append(w)

    @property
    def item_list(self):
        self.__init_fullpathlist__()
        return random_copy(self.request, self.__item_list__)

    @property
    def url_thumbnail(self):
        return pygal.url_thumbnail(self. request, self.item.thumbnail_item().rel_path)


class image_view(base_view):
    def __init__(self, *args, **kwargs):
        base_view.__init__(self, *args, **kwargs)
        #
        self.template = 'pygal/image.html'

    def __actionbar__(self):
        b = base_view.__actionbar__(self)
        gps_data = self.item.item_data.gps
        if gps_data is not None:
            b.append_entry(
                'actionbar-gpslink',
                _('GPS'),
                themes.color_icon_url(self.request, 'gps.png'),
                geo.osm.landmark_link(geo.gps.coordinate(**gps_data)),
                True,
                False
            )
        return b

    @property
    def width(self):
        if self.item.item_data.orientation in [5, 6, 7, 8]:
            return self.item.item_data.height
        else:
            return self.item.item_data.width

    @property
    def height(self):
        if self.item.item_data.orientation in [5, 6, 7, 8]:
            return self.item.item_data.width
        else:
            return self.item.item_data.height


class video_view(base_view):
    def __init__(self, *args, **kwargs):
        base_view.__init__(self, *args, **kwargs)
        #
        self.template = 'pygal/video.html'

    @property
    def use_internal_player(self):
        return self.mime_type in [mimetypes.types_map.get(ext) for ext in ['.mp4', '.webm', '.ogv', '.flv', '.3gp', ]]

    @property
    def webnail_width(self):
        w, h = self.item.item_data.width, self.item.item_data.height
        return int(pygal.get_webnail_size(self.request) * w / max(w, h))

    @property
    def webnail_height(self):
        w, h = self.item.item_data.width, self.item.item_data.height
        return int(pygal.get_webnail_size(self.request) * h / max(w, h))


class audio_view(base_view):
    def __init__(self, *args, **kwargs):
        base_view.__init__(self, *args, **kwargs)
        #
        self.template = 'pygal/audio.html'

    @property
    def heading(self):
        return '%02d - %s' % (self.item.item_data.track, self.item.item_data.title)


class other_view(base_view):
    def __init__(self, *args, **kwargs):
        base_view.__init__(self, *args, **kwargs)
        #
        self.template = 'pygal/other.html'
