
import json
import urllib2
import os
from string import Template
from decimal import Decimal

# database stuff
from sqlalchemy.exc import DBAPIError
from sqlalchemy import or_
from climasng.models import *

from climasng.parsing.prosemaker import ProseMaker

class DocAssembler(object):

    def __init__(self, doc_data, section_data, settings={}):
        self._defaults = {
            # pattern can use region_id and region_type to make a url
            'region_url_pattern': 'http://localhost:6543/regiondata/${region_type}/${region_id}',
        }
        # merge in the user settings
        self._settings = dict(self._defaults.items() + settings.items())

        self._doc_data = doc_data
        self._sect_data = section_data
        self._region_type = doc_data['regiontype']
        self._region_id = doc_data['regionid']
        self._region_url_template = Template(self._settings['region_url_pattern'])
        self._region_data_path_template = Template(self._settings['region_data_path_pattern'])
        self._selected_sections = doc_data['selected_sections']
        self._format = doc_data['format']
        self._year = doc_data['year']

        self.getRegionData()
        self.getSource()


    def getRegionData(self, region_id=None, region_type=None):
        region_type = self._region_type if region_type is None else region_type
        region_id = self._region_id if region_id is None else region_id

        self._region = {
            'year': self._year,
            'region_type': region_type,
            'region_id': region_id
        }
        # resolve the region url template with region info
        self._region['region_url'] = self._region_url_template.substitute(self._region)
        self._region['region_data_path'] = self._region_data_path_template.substitute(self._region)

        # add the old climate info
        clim_json_string = urllib2.urlopen(self._region['region_url'] + '/climate').read()
        clim_data = json.loads(
            clim_json_string,
            parse_float=Decimal, parse_int=Decimal, parse_constant=Decimal
        )
        self._region.update(clim_data) # merge, clim wins

        # add the new biodiveristy data
        biodiv_json_string = urllib2.urlopen(self._region['region_url'] + '/biodiversity').read()
        biodiv_data = json.loads(
            biodiv_json_string,
            parse_float=Decimal, parse_int=Decimal, parse_constant=Decimal
        )
        self._region.update(biodiv_data) # merge, biodiv wins

        self.addSectionsToData() # add indicators showing included sections

        # raise Exception(region_data_url)
        # raise Exception(self._region)
        # raise Exception(self._sections)

        return self._region


    def getSource(self):
        sources = []
        for sect in self._sect_data:
            if sect.id in self._selected_sections:
                sources.append(self.getSectionSource(sect))
        self._source = ''.join(sources)
        return self._source


    def addSectionsToData(self):
        for sect in self._sect_data:
            if sect.id in self._selected_sections:
                self._region['section_' + sect.id.replace('.', '_')] = Decimal(1)
            else:
                self._region['section_' + sect.id.replace('.', '_')] = Decimal(0)


    def getSectionSource(self, sect):
        try:
            source = []
            with open(sect.contentpath) as contentf:
                # start with the normal content
                source.append( contentf.read() )
                # if it's a query, run the query and append the result
                if sect.is_query:
                    with open(sect.querypath) as qf, open(sect.rowtemplatepath) as rtf:
                        query = qf.read()
                        region_name = ' '.join(self._region_id.split('_')[1:])
                        print(region_name)
                        result_set = DBSession.execute(query, {
                            "year": self._year,
                            "regionname": region_name,
                            "regiontype": self._region_type
                        })
                        # separate template for odd and even rows
                        even_row = Template(rtf.read())
                        odd_row = even_row
                        if sect.has_oddrowtemplate:
                            with open(sect.oddrowtemplatepath) as ortf:
                                odd_row = Template(ortf.read())
                        index = -1
                        # now resolve the row template with this row's data
                        for result in result_set:
                            index += 1
                            if index % 2 != 0:
                                source.append(odd_row.safe_substitute(result))
                            else:
                                source.append(even_row.safe_substitute(result))

                return ''.join(source)

        except IOError as e:
            return ''


    def result(self):
        pm = ProseMaker()
        pm.data = self._region
        pm.source = self._source

        # currently returning raw Markdown.
        return pm.doc


@@ -1153,16 +1153,90 @@
 year'%5D%0A%0A
+        self._section_debug = self._settings.get('section_debug', False)%0A%0A
         
@@ -3446,24 +3446,593 @@
 source = %5B%5D%0A
+            if self._section_debug:%0A                # work out a shortish path to this section%0A                this_file_dirs = __file__.split(os.path.sep)%0A                sect_dirs = sect.contentpath.split(os.path.sep)%5B:-1%5D%0A                for dir in this_file_dirs:%0A                    if sect_dirs%5B0%5D == dir:%0A                        sect_dirs = sect_dirs%5B1:%5D%0A                    else:%0A                        break%0A                # write out the shortish path to the content%0A                source.append(%22%5Cn%5Cn* * *%5Cn( %60%22 + os.path.sep.join(sect_dirs) + %22%60 )%5Cn%5Cn%22)%0A
             
@@ -4068,24 +4068,24 @@
 s contentf:%0A
-
             
@@ -4396,32 +4396,32 @@
 ery = qf.read()%0A
+
                 
@@ -4487,51 +4487,8 @@
 :%5D)%0A
-                        print(region_name)%0A
     

debug option for doc assembly that drops the section filename into the doc