import json
import os

from django.views.generic import TemplateView, FormView
from django.views.generic.base import View
from django.shortcuts import HttpResponse
from django.http import HttpResponseBadRequest
from django.core.urlresolvers import reverse_lazy
from django.core.files.base import ContentFile

from filemanager.forms import DirectoryCreateForm
from filemanager.settings import MEDIA_ROOT, MEDIA_URL, STORAGE
from filemanager.utils import sizeof_fmt
from filemanager.core import Filemanager


def get_abspath(relpath):
    return os.path.join(MEDIA_ROOT, relpath)

def get_absurl(relurl):
    return os.path.join(MEDIA_URL, relurl)


class FilemanagerMixin(object):
    def __init__(self, *args, **kwargs):

        self.storage = STORAGE

        return super(FilemanagerMixin, self).__init__(*args, **kwargs)

    def get_context_data(self, *args, **kwargs):
        context = super(FilemanagerMixin, self).get_context_data(*args, **kwargs)

        self.fm = Filemanager(self.get_relpath())
        self.fm.patch_context_data(context)

        if hasattr(self, 'extra_breadcrumbs') and isinstance(self.extra_breadcrumbs, list):
            context['breadcrumbs'] += self.extra_breadcrumbs

        return context

    def get_relpath(self):
        if 'path' in self.request.GET and len(self.request.GET['path']) > 0:
            return os.path.relpath(self.request.GET['path'])
        if 'path' in self.request.POST and len(self.request.POST['path']) > 0:
            return os.path.relpath(self.request.POST['path'])
        return ''


class BrowserView(FilemanagerMixin, TemplateView):
    template_name = 'filemanager/browser/filemanager_list.html'

    def get_context_data(self, **kwargs):
        context = super(BrowserView, self).get_context_data(**kwargs)

        context['files'] = []

        directories, files = self.storage.listdir(self.fm.location)

        for directoryname in directories:
            context['files'].append({
                'filepath': os.path.join(self.fm.path, directoryname),
                'filetype': 'Directory',
                'filename': directoryname,
                'filesize': '-',
                'filedate': self.storage.modified_time(os.path.join(self.fm.location, directoryname))
            })

        for filename in files:
            abspath = os.path.join(self.fm.location, filename)
            context['files'].append({
                'filepath': os.path.join(self.fm.path, filename),
                'filetype': 'File',
                'filename': filename,
                'filesize': sizeof_fmt(self.storage.size(abspath)),
                'filedate': self.storage.modified_time(abspath)
            })

        return context


class DetailView(FilemanagerMixin, TemplateView):
    template_name = 'filemanager/browser/filemanager_detail.html'

    def get_context_data(self, **kwargs):
        context = super(DetailView, self).get_context_data(**kwargs)

        filename = self.fm.path.rsplit('/', 1)[-1]

        context['file'] = {
            'filepath': self.fm.path[:-len(filename)],
            'filename': filename,
            'filesize': sizeof_fmt(self.storage.size(self.fm.location)),
            'filedate': self.storage.modified_time(self.fm.location),
            'fileurl': self.fm.url,
        }

        return context


class UploadView(FilemanagerMixin, TemplateView):
    template_name = 'filemanager/filemanager_upload.html'
    extra_breadcrumbs = [{
        'path': '#',
        'label': 'Upload'
    }]


class UploadFileView(FilemanagerMixin, View):
    def post(self, request, *args, **kwargs):
        if len(request.FILES) != 1:
            return HttpResponseBadRequest("Just a single file please.")

        filedata = request.FILES['files[]']

        filepath = os.path.join(self.get_relpath(), self.storage.get_valid_name(filedata.name))

        # TODO: get filepath and validate characters in name, validate mime type and extension

        self.storage.save(filepath, filedata)

        return HttpResponse(json.dumps({
            'files': [{'name': filedata.name}],
        }))


class DirectoryCreateView(FilemanagerMixin, FormView):
    template_name = 'filemanager/filemanager_create_directory.html'
    form_class = DirectoryCreateForm
    extra_breadcrumbs = [{
        'path': '#',
        'label': 'Create directory'
    }]

    def get_success_url(self):
        return reverse_lazy('filemanager:browser') + '?path=' + self.get_relpath()

    def form_valid(self, form):
        directory_name = self.storage.get_valid_name(form.cleaned_data.get('directory_name'))

        directory_path = os.path.join(directory_name, '.tmp')

        path = os.path.join(self.get_relpath(), directory_path)

        self.storage.save(path, ContentFile(''))
        self.storage.delete(path)

        return super(DirectoryCreateView, self).form_valid(form)

@@ -388,31 +388,8 @@
 port
- MEDIA_ROOT, MEDIA_URL,
  STO
@@ -393,16 +393,16 @@
 STORAGE%0A
+
 from fil
@@ -481,149 +481,8 @@
 r%0A%0A%0A
-def get_abspath(relpath):%0A    return os.path.join(MEDIA_ROOT, relpath)%0A%0Adef get_absurl(relurl):%0A    return os.path.join(MEDIA_URL, relurl)%0A%0A%0A
 clas
@@ -651,24 +651,377 @@
  **kwargs)%0A%0A
+    def dispatch(self, request, *args, **kwargs):%0A        params = dict(request.GET)%0A        params.update(dict(request.POST))%0A%0A        self.fm = Filemanager()%0A        if 'path' in params and len(params%5B'path'%5D%5B0%5D) %3E 0:%0A            self.fm.update_path(params%5B'path'%5D%5B0%5D)%0A%0A        return super(FilemanagerMixin, self).dispatch(request, *args, **kwargs)%0A%0A
     def get_
@@ -1144,58 +1144,8 @@
 s)%0A%0A
-        self.fm = Filemanager(self.get_relpath())%0A
     
@@ -1339,16 +1339,16 @@
 crumbs%0A%0A
+
         
@@ -1367,333 +1367,8 @@
 xt%0A%0A
-    def get_relpath(self):%0A        if 'path' in self.request.GET and len(self.request.GET%5B'path'%5D) %3E 0:%0A            return os.path.relpath(self.request.GET%5B'path'%5D)%0A        if 'path' in self.request.POST and len(self.request.POST%5B'path'%5D) %3E 0:%0A            return os.path.relpath(self.request.POST%5B'path'%5D)%0A        return ''%0A%0A
 %0Acla
@@ -3611,29 +3611,23 @@
 in(self.
-get_rel
+fm.
 path
-()
 , self.s
@@ -4263,29 +4263,23 @@
  + self.
-get_rel
+fm.
 path
-()
 %0A%0A    de
@@ -4499,21 +4499,15 @@
 elf.
-get_rel
+fm.
 path
-()
 , di

use filemanager verywhere in views and move dedicated get and post handling to one dispatch function