#!/srv/venv/bin/python
""" Process emails """
import sys
import os

import zipfile
import re
import time
from time import strftime

from django.core.management.base import BaseCommand
from django_mailbox.models import Message, MessageAttachment,Mailbox
from django.core.urlresolvers import reverse
from django.conf import settings

from rowers.models import Workout, Rower

from rowingdata import rower as rrower
from rowingdata import rowingdata as rrdata

import rowers.uploads as uploads
from rowers.mailprocessing import make_new_workout_from_email, send_confirm

workoutmailbox = Mailbox.objects.get(name='workouts')
failedmailbox = Mailbox.objects.get(name='Failed')

# If you find a solution that does not need the two paths, please comment!
sys.path.append('$path_to_root_of_project$')
sys.path.append('$path_to_root_of_project$/$project_name$')

os.environ['DJANGO_SETTINGS_MODULE'] = '$project_name$.settings'

if not getattr(__builtins__, "WindowsError", None):
    class WindowsError(OSError): pass

def rdata(file_obj, rower=rrower()):
    """ Read rowing data file and return 0 if file doesn't exist"""
    try:
        result = rrdata(file_obj, rower=rower)
    except IOError:
        result = 0

    return result

def processattachment(rower, fileobj, title, uploadoptions,testing=False):
    try:
        filename = fileobj.name
    except AttributeError:
        filename = fileobj[6:]

        
    # test if file exists and is not empty
    try:
        with open('media/'+filename,'r') as fop:
            line = fop.readline()
    except IOError:
        return 0

    workoutid = [
        make_new_workout_from_email(rower, filename, title,testing=testing)
    ]

    if workoutid[0]:
        link = settings.SITE_URL+reverse(
            rower.defaultlandingpage,
            kwargs = {
                'id':workoutid[0],
            }
        )

        if uploadoptions and not 'error' in uploadoptions:
            workout = Workout.objects.get(id=workoutid[0])
            uploads.do_sync(workout, uploadoptions)
            uploads.make_private(workout, uploadoptions)
        if 'make_plot' in uploadoptions:
            plottype = uploadoptions['plottype']
            workoutcsvfilename = workout.csvfilename[6:-4]
            timestr = strftime("%Y%m%d-%H%M%S")
            imagename = workoutcsvfilename + timestr + '.png'
            result,jobid = uploads.make_plot(
                workout.user, workout, workoutcsvfilename,
                workout.csvfilename,
                plottype, title,
                imagename=imagename
            )
        try:
            if workoutid and not testing:
                email_sent = send_confirm(
                    rower.user, title, link,
                    uploadoptions
                )
                time.sleep(10)
        except:
            try:
                if not testing:
                    time.sleep(10)
                    if workoutid:
                        email_sent = send_confirm(
                            rower.user, title, link,
                            uploadoptions
                        )
            except:
                pass

    return workoutid

def get_from_address(message):

    from_address = message.from_address[0].lower()
    
    if message.encoded:
        body = message.text.splitlines()
    else:
        body = message.get_body().splitlines()

    try:
        first_line = body[0].lower()
    except IndexError:
        first_line = ''

    if "quiske" in first_line:
        match = re.search(r'[\w\.-]+@[\w\.-]+', first_line)
        return match.group(0)

    return from_address


class Command(BaseCommand):
    def add_arguments(self, parser):
        parser.add_argument(
            '--testing',
            action='store_true',
            dest='testing',
            default=False,
            help="Run in testing mode, don't send emails",
            )
    
    """Run the Email processing command """
    def handle(self, *args, **options):
        messages = Message.objects.filter(mailbox_id = workoutmailbox.id)
        message_ids = [m.id for m in messages]
        attachments = MessageAttachment.objects.filter(
            message_id__in=message_ids
        )
        if 'testing' in options:
            testing = options['testing']
        else:
            testing = False
        cntr = 0
        for attachment in attachments:
            extension = attachment.document.name[-3:].lower()
            try:
                message = Message.objects.get(id=attachment.message_id)
                if message.encoded:
#                if message.text:
                    body = "\n".join(message.text.splitlines())
                else:
                    body = message.get_body()
                    
                uploadoptions = uploads.upload_options(body)

                from_address = get_from_address(message)
                
                name = message.subject
                # get a list of users
                # theusers = User.objects.filter(email=from_address)
                rowers = [
                    r for r in Rower.objects.all() if r.user.email.lower() == from_address
                ]
            except IOError:
                rowers = []
            for rower in rowers:
                if extension == 'zip':
                    zip_file = zipfile.ZipFile(attachment.document)
                    for id,filename in enumerate(zip_file.namelist()):
                        datafile = zip_file.extract(filename, path='media/')
                        if id>0:
                            title = name+' ('+str(id+1)+')'
                        else:
                            title = name
                            
                        workoutid = processattachment(
                            rower, datafile, title, uploadoptions,
                            testing=testing
                        )
                else:
                    # move attachment and make workout
                    workoutid = processattachment(
                        rower, attachment.document, name, uploadoptions,
                        testing=testing
                    )

            # We're done with the attachment. It can be deleted
            try:
                attachment.delete()
            except IOError:
                pass
            except WindowsError:
                if not testing:
                    time.sleep(2)
                try:
                    attachment.delete()
                except WindowsError:
                    pass
            except:
                message.mailbox = failedmailbox
                message.save()

            if message.attachments.exists() is False:
                # no attachments, so can be deleted
                message.delete()

        messages = Message.objects.all()
        for message in messages:
            if message.attachments.exists() is False:
                message.delete()

        self.stdout.write(self.style.SUCCESS(
            'Successfully processed email attachments'))
