import alot
import os
import re
import subprocess
import asyncio
import shlex
import magic
from notmuch.thread import Thread
from notmuch.message import Message


def pre_buffer_focus(ui, dbm, buf):
    if isinstance(buf, alot.buffers.SearchBuffer):
        buf.rebuild()


# TODO: async
# mark current message read at github
def github_mark_read(ui, msg=None):
    if msg is None:
        msg = ui.current_buffer.get_selected_message()
    msg = msg.get_email()

    if msg.is_multipart():
        msgtext = b""
        for msgpart in msg.get_payload():
            msgtext += msgpart.get_payload(decode=True)
    else:
        msgtext = msg.get_payload(decode=True)

    r = b'src="(https://github.com/notifications/beacon/.*.gif)"'
    beacons = re.findall(r, msgtext)

    if beacons:
        subprocess.Popen(['curl', '-s', beacons[0]], stdout=open(os.devnull, 'w'))
        ui.notify('removed from github notifications:\n %s' % beacons[0])
    else:
        ui.notify('no beacon found')


# automatically mark github notifications as read
async def post_search_select(ui, cmd, dbm):
    current_msg = ui.current_buffer.get_selected_message()
    if current_msg.get_author()[1] == 'notifications@github.com':
        last_msg = list(ui.current_buffer.messagetrees())[-1]._message
        if 'unread' in last_msg.get_tags():
            github_mark_read(ui, list(ui.current_buffer.messagetrees())[-1]._message)


# command to manually fetch mails
def getmails(ui):
    ui.notify("fetchinig email..")
    subprocess.call(['pkill', '-u', os.environ['USER'], '-USR1', 'maildaemon'])


def exit():
    subprocess.call(['notmuch-backup'])


def _sorted_func(func, key):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        return sorted(result, key=key)
    return wrapper


async def post_thread_save(ui, dbm, cmd):
    # we are only concerned when we saved a single focused attachment
    if cmd.all or not cmd.path:
        return

    if magic.from_file(cmd.path).endswith(' text, with CRLF line terminators'):
        if (await ui.choice("convert Windows text file?", select='yes', cancel='no')) == 'no':
            return
        process = await asyncio.create_subprocess_exec('dos2unix', cmd.path)
        await process.wait()
    if magic.from_file(cmd.path).startswith('ISO-8859 text'):
        if (await ui.choice("convert ISO-8859 text file?", select='yes', cancel='no')) == 'no':
            return
        process = await asyncio.create_subprocess_shell('iconv -f latin1 -t utf8 {0} | sponge {0}'.format(shlex.quote(cmd.path)))
        await process.wait()


def unsubscribe_list(ui):
    """
    Unsubscribe from a mailing list.

    This hook reads the 'List-Unsubscribe' header of a mail in thread mode,
    constructs a unsubsribe-mail according to any mailto-url it finds
    and opens the new mail in an envelope buffer.
    """
    from alot.helper import mailto_to_envelope
    from alot.buffers import EnvelopeBuffer
    msg = ui.current_buffer.get_selected_message()
    e = msg.get_email()
    uheader = e['List-Unsubscribe']
    dtheader = e.get('Delivered-To', None)

    if uheader is not None:
        M = re.search(r'<(mailto:\S*)>', uheader)
        if M is not None:
            env = mailto_to_envelope(M.group(1))
            if dtheader is not None:
                env['From'] = dtheader
            ui.buffer_open(EnvelopeBuffer(ui, env))
    else:
        ui.notify('focussed mail contains no \'List-Unsubscribe\' header',
                  'error')


Thread.get_toplevel_messages = _sorted_func(Thread.get_toplevel_messages,
                                            Message.get_date)

@@ -1,16 +1,4 @@
-import alot%0A
 impo
@@ -3,16 +3,16 @@
 port os%0A
+
 import r
@@ -81,36 +81,233 @@
 rom 
-notmuch.thread import Thread
+alot.buffers import EnvelopeBuffer, SearchBuffer%0Afrom alot.commands import CommandCanceled%0Afrom alot.helper import mailto_to_envelope%0Afrom alot.settings.const import settings%0Afrom alot.settings.errors import NoMatchingAccount
 %0Afro
@@ -339,16 +339,50 @@
 Message%0A
+from notmuch.thread import Thread%0A
 %0A%0Adef pr
@@ -411,16 +411,16 @@
 , buf):%0A
+
     if i
@@ -438,21 +438,8 @@
 uf, 
-alot.buffers.
 Sear
@@ -3079,99 +3079,8 @@
 %22%22%22%0A
-    from alot.helper import mailto_to_envelope%0A    from alot.buffers import EnvelopeBuffer%0A
     
@@ -3266,17 +3266,28 @@
         
-M
+mailto_match
  = re.se
@@ -3330,17 +3330,28 @@
      if 
-M
+mailto_match
  is not 
@@ -3371,16 +3371,21 @@
      env
+elope
  = mailt
@@ -3398,17 +3398,28 @@
 nvelope(
-M
+mailto_match
 .group(1
@@ -3477,16 +3477,21 @@
      env
+elope
 %5B'From'%5D
@@ -3502,16 +3502,377 @@
 theader%0A
+                try:%0A                    envelope.account = settings.account_matching_address(dtheader)%0A                except NoMatchingAccount:%0A                    msg = 'Cannot compose mail - ' %5C%0A                          'no account found for %60%25s%60' %25 dtheader%0A                    ui.notify(msg, priority='error')%0A                    raise CommandCanceled()%0A
         
@@ -3912,16 +3912,21 @@
 (ui, env
+elope
 ))%0A    e

fix unsubscribe hook