from django.db import models
from tagging.fields import TagField
from oxdjango.fields import DictField
from tagging.models import Tag
from django.contrib.auth.models import User, Group, Permission
import os
from os.path import join
from convert import convertFile
from django.db.models.signals import post_save
from settings import UPLOAD_ROOT, MEDIA_ROOT
from utils.add_file import hashFile, fileInfo, getFileType
from django.core.files.base import ContentFile
import operator
from django.db.models import Q
from ox.text import smartSplit
from sorl.thumbnail import get_thumbnail

#FIXME: The following two functions are ridiculous. please remove and clean up all references to them.
def baseFileName(filename):
  r = filename.rindex('.')
  return filename[0:r]

def extFileName(filename):
  r = filename.rindex('.') + 1
  return filename[r:]

def splitSearch(string):
  ret = []
  for s in smartSplit(string):
    word = s.replace("'", "").replace('"', '')
    ret.append(word)
  return ret


MIME_TYPES = (
    ('jpg', 'Image'),
    ('png', 'Image'),
    ('ogv', 'Video'),
    ('mp3', 'Audio (mp3)'),
    ('ogg', 'Audio (Ogg)'),
    ('txt', 'Text'),
    ('oth', 'Other'),
    ('hid', 'Hidden'),
)

TYPE_CHOICES = (
  ('', '---'),
  ('image', 'Image'),
  ('audio', 'Audio'),
  ('text', 'Text'),
  ('video', 'Video'),
  ('other', 'Other'),
)

class Folder(models.Model):
  name = models.CharField(max_length=1024)
  relative_path = models.CharField(max_length=2048)
  parent = models.ForeignKey("Folder")
  category = models.ForeignKey("Category")
  
  def get_full_path(self):
    return join(UPLOAD_ROOT, self.category.folder_name, self.relative_path) 

  def get_children(self):
    return Folder.objects.filter(parent=self)
    
  def has_parent(self):
    if self.name == self.category.folder_name:
      return False
    else:
      return True

  def get_files(self):
    return File.objects.filter(folder=self)

  def get_dict(self):
    return {
      'files': self.get_files(),
      'folders': self.get_children(),
      'parent': self.parent,
      'name': self.name,
      'fullPath': self.fullPath
    }    


class File(models.Model):
  file = models.FileField('File', upload_to=UPLOAD_ROOT, max_length=1024)
  full_path = models.CharField(max_length=2048, blank=True, db_index=True) #makes it more efficient to retrieve a file by path instead of using self.file.path
  title = models.CharField(max_length=255)
  done = models.BooleanField(default=False)
  description = models.TextField(blank=True)
  tags = TagField("Tags", help_text="Enter as many tags as you like, separated by commas")
  userID = models.ForeignKey(User)
  file_date = models.DateField("Date", blank=True, null=True)
  added = models.DateTimeField("Date Added", auto_now_add=True)
  categories = models.ManyToManyField('Category', verbose_name='Studies')
  private = models.BooleanField(default=False)
#  type = models.ForeignKey('Type', verbose_name='File Type')
  type = models.CharField(max_length=255, choices=TYPE_CHOICES)
  ext = models.CharField(max_length=100, blank=True)
  oshash = models.CharField(max_length=128, blank=True, db_index=True)
#  folder = models.ForeignKey("Folder")
  info = models.CharField(max_length=1024, blank=True, null=True)

  fts_fields = ['title', 'description']

  class Meta:
    ordering = ['-added']

  @classmethod
  def filter_category(kls, category_id, qset):
    return qset.filter(categories=category_id)

  @classmethod
  def filter_type(kls, typ, qset):
    return qset.filter(type__iexact=typ)

  @classmethod
  def fts(kls, search, qset):
    terms = splitSearch(search)
    qobjects = []
    for t in terms:  
      for f in kls.fts_fields:
        qstring = f + '__icontains'
        qobject = Q(**{qstring:t})
        qobjects.append(qobject)
    return qset.filter(reduce(operator.or_, qobjects))

  def get_thumb(self, size):
    if self.ext.lower() in ['jpg', 'jpeg', 'png']:
      return get_thumbnail(open(self.file.path), size, crop="center", quality=60).url
    else:
      return self.ext

  def get_dict(self):
    #FIXME
    try:
      url = self.file.url
      if self.type.lower() == 'image':
        thumbnail = get_thumbnail(open(self.file.path), "400x300", crop='center', quality=60).url
      else:
        thumbnail = ''
    except:
      url = ''    
      thumbnail = ''
    studies = [{'id': s.id, 'name': s.name} for s in self.categories.all()]
    return {
      'id': self.id,
      'url': url,
      'thumbnail': thumbnail,
      'title': self.title,
      'description': self.description,
      'type': self.type,
      'studies': studies,
      'is_private': self.private
    }

  def save_chunk(self, chunk, name='data.bin'):
    if not self.done:
      if not self.file:
        self.file.save(name, ContentFile(chunk))
        self.title = name
        self.save()
      else:
        f = open(self.file.path, 'a')
        f.write(chunk)
        f.close()
      return True
    return False



  @classmethod
  def add_from_path(cls, category, user, path, **kwargs):
    if cls.objects.filter(full_path=path).count() > 0:
      #Do update checking here. For now, we move on if it already exists in db
      return False
    info = fileInfo(path)
    oshash = hashFile(path)
    dirname = os.path.dirname(path)
    filename = os.path.basename(path)
    title = kwargs.get("title", filename)
    description = kwargs.get("description", "")
    ext = os.path.splitext(filename)[1][1:].lower()
    typ = getFileType(path, ext)
    django_file_path = join(path.replace(MEDIA_ROOT, "")[1:])
    f = cls(file=django_file_path, full_path=path, title=title, description=description, ext=ext, type=typ, oshash=oshash, info=info)
    f.userID = user
    f.save()
    f.categories.add(category)
#    f.save()
    return f

  @classmethod
  def addFiles(cls, category, user, folder_name):
    path = join(UPLOAD_ROOT, folder_name)
  #  spider(path, addFile, category=category)
    for dirpath, dirnames, filenames in os.walk(path):
      if filenames:
  #            prefix = dirpath[len(path)+1:]
        for filename in filenames:
          if not filename.startswith('._') and not filename in ('.DS_Store', ):
            cls.add_from_path(category, user, join(dirpath, filename))
  #                    print dirpath  + " + " + filename
             
  def __unicode__(self):
    return self.title

  def original_print(self):
    '''
    basePath = "media/images/original/"
    filename = os.path.basename(str(self.file.url))
    if extFileName(filename).lower() != 'jpg':
      f = baseFileName(filename) + ".jpg"
    else:
      f = filename
    '''
    return str(self.file)

  def move_to(self, study):
    self.categories.clear()
    self.categories.add(study)
    self.save()
    return self  

  def can_edit(self, user):
    if user.is_superuser or self.userID == user:
      return True
    else:
      return False

class Category(models.Model):
  name = models.CharField(max_length=255)
  groups = models.ManyToManyField(Group, null=True)
#  folder_name = models.CharField(max_length=512)

  def __unicode__(self):
    return self.name

  class Meta:
    ordering = ['name']
    verbose_name = 'Study'
    verbose_name_plural = 'Studies'

class Type(models.Model):
  name = models.CharField(max_length=255)
  mime = models.CharField(choices=MIME_TYPES, verbose_name="Type of File", blank=True, null=True, max_length=20)  
#  mim = models.ChoiceField(choices=MIME_TYPES)  
  def __unicode__(self):
    return "%s - %s" % (self.name, self.mime)

  class Meta:
    verbose_name = 'File Type'
    verbose_name_plural = 'File Types'

post_save.connect(convertFile, sender=File)
