# Copyright (C) 2012 Alex Nisnevich
# Licensed under the MIT license

from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals

import re

try:
    from http.client import HTTPConnection
    from urllib.parse import urlencode
except ImportError:
    from httplib import HTTPConnection
    from urllib import urlencode

from MarkdownPP.Module import Module
from MarkdownPP.Transform import Transform

# $...$ (or $$...$$)
singlelinere = re.compile("\$(\$?)..*\$(\$?)")
# $... or ...$ (or $$... or ...$$)
startorendre = re.compile("^\$(\$?)|^\S.*\$(\$?)$")

codere = re.compile("^(    |\t)")
spancodere = re.compile(r'(`[^`]+\`)')  # code between backticks

# Support for Pandoc style code blocks with attributes
fencedcodere = re.compile("^((> *)?```\w*|(> *)?~~~~*(\s*{.*})?)$")


class LaTeXRender(Module):
    """
    Module for rendering LaTeX enclosed between $ dollar signs $.
    Rendering is performed using QuickLaTeX via ProblemSetMarmoset.
    """

    def transform(self, data):
        transforms = []
        linenum = 0
        in_block = False
        current_block = ""
        in_fenced_code_block = False

        for line in data:
            # Handling fenced code blocks (for Github-flavored markdown)
            if fencedcodere.search(line):
                if in_fenced_code_block:
                    in_fenced_code_block = False
                else:
                    in_fenced_code_block = True

            # Are we in a code block?
            if not in_fenced_code_block and not codere.search(line):
                # Is this line part of an existing LaTeX block?
                if in_block:
                    transforms.append(Transform(linenum, "drop"))
                    current_block += "\n" + line

                match = singlelinere.search(line)
                if match:
                    code_pos = []
                    for m in spancodere.finditer(line):
                        code_pos += range(*m.span())

                    if not (match.start(0) in code_pos or
                            match.end(0) in code_pos):

                        # Single LaTeX line
                        tex = match.group(0)
                        before_tex = line[0:line.find(tex)]
                        after_tex = line[(line.find(tex) + len(tex)):
                                         len(line)]
                        transforms.append(Transform(linenum, "swap",
                                                    before_tex +
                                                    self.render(tex) +
                                                    after_tex))
                else:
                    match = startorendre.search(line)
                    if match:
                        # Starting or ending a multi-line LaTeX block
                        if in_block:
                            # Ending a LaTeX block
                            transforms.pop()  # undo last drop
                            transforms.append(Transform(linenum, "swap",
                                              self.render(current_block)))
                        else:
                            # Starting a LaTeX block
                            current_block = line
                            transforms.append(Transform(linenum, "drop"))
                        in_block = not in_block

            linenum += 1

        return transforms

    def render(self, formula):
        # Prepare the formula
        formula = formula.replace("$", "")
        encoded_formula = formula.replace("%", "[comment]").replace("+", "%2B")
        display_formula = formula.replace("\n", "")
        print('Rendering: %s ...' % display_formula)

        # Prepare POST request to QuickLaTeX via ProblemSetMarmoset
        # (for added processing)
        params = urlencode({
            'engine': 'quicklatex',
            'input': encoded_formula,
        })
        headers = {"Content-type": "application/x-www-form-urlencoded",
                   "Accept": "text/plain"}
        conn = HTTPConnection("www.problemsetmarmoset.com")

        # Make the request
        conn.request("POST", "/latex/render.php", params, headers)
        response = conn.getresponse()
        img_url = response.read()
        conn.close()

        # Display as Markdown image
        rendered_tex = '![{0}]({1} "{0}")\n'.format(display_formula,
                                                    img_url.decode('utf-8'))
        return rendered_tex

@@ -190,16 +190,47 @@
 mport re
+%0Afrom contextlib import closing
 %0A%0Atry:%0A 
@@ -4103,24 +4103,25 @@
 plain%22%7D%0A
+%0A
         
 conn = H
@@ -4116,15 +4116,48 @@
     
-conn = 
+# Make the request%0A        with closing(
 HTTP
@@ -4200,37 +4200,23 @@
 om%22)
-%0A%0A        # Make the request%0A
+) as conn:%0A    
     
@@ -4278,16 +4278,20 @@
 eaders)%0A
+    
         
@@ -4324,24 +4324,28 @@
 e()%0A        
+    
 img_url = re
@@ -4361,29 +4361,8 @@
 ad()
-%0A        conn.close()
 %0A%0A  

use contextlib.closing instead of calling close()