<file_sep>"""
Created on Sep 19, 2014

@author: memery
"""
import re
import csv
import time
import collections
import os
import codecs


class Newsletter(object):
    """The Newsletter class simply requires a plaintext to function.
    [ADD MORE HERE]"""
    content = []
    flag_library = {}
    output = []

    def __init__(self, plaintext):
        self.plaintext = plaintext
        assert type(self.plaintext) == file, 'plaintext is not a file!'

    def _content_from_plaintext(self):
        """This method reads the Newsletter's plaintext and populates the flag
        library"""
        with self.plaintext as source:
            self.content = [line.decode('utf-8').strip('\n') for line in source]

        self.plaintext.close()

    def _find_plaintext_directory(self):
        """Returns directory where self.plaintext is located"""
        return os.path.dirname(self.plaintext)

    def _index_flags(self):
        """Creates a default dictionary that returns a tuple containing a
        sentinal string and all indices where that string appears"""
        flag_dict = {
            '>>-->>Banner 1 Name>>': 'banners',
            '>>-->>Banner 2 Name>>': 'banners',
            '>>-->>Banner 3 Name>>': 'banners',
            '>>-->>MP_Banner Name>>': 'banners',
            '>>-->>Text Banner Name>>': 'textbanner',
            '>>-->>Publication>>': 'pubs',
            '>>-->>Review>>': 'revs',
            '>>-->>Industry Title>>': 'inds',
            '>>-->>Science Title>>': 'scis',
            '>>-->>Policy Title>>': 'pols',
            '>>-->>NIH Title>>': 'regs',
            '>>-->>CBER Title>>': 'regs',
            '>>-->>Regulatory Title>>': 'regs',
            '>>-->>Event Title>>': 'events',
            '>>-->>Job Title>>': 'jobs',
            '>>-->>Newsletter Name>>': 'nl',
            '>>-->>Newsletter Issue Number>>': 'issue',
            '>>-->>Connexon Banner Name>>': 'cxnbanner',
            '>>-->>Newsletter Issue Date>>': 'date',
            '>>-->>Subject Line>>': 'subjectline',
            '>>-->>Homepage Banner Name>>': 'hpbanner',
            '>>-->>Old Jobs>>': 'oldjobs',
            ">>-->>Insert last week's jobs' HTML here>>": 'prevjobs',
            '>>-->>end of plaintext>>-->>': 'end',
        }

        # Could still be better (Nested loop is ugly)
        line_count = 0
        self.flag_library = collections.defaultdict(list)
        for line in self.content:
            for flag in flag_dict:
                if flag in line:
                    self.flag_library[flag_dict[flag]].append(line_count)
            line_count += 1

    def _index_content(self, index, offset=0):
        """returns the line in self.content equal to the value of index plus
        the value of offset. Default offset is 0."""
        return self.content[index + offset]

    def _object_builder(self, index, theclass, offset_sequence):
        """Magic. Constructs any type of object (Banner/Article etc.) given
        a starting index, the class and the sequence the offsets"""
        attributes = [self._index_content(index, offset) for offset in offset_sequence]
        return theclass(*attributes)

    def _object_builder_dict(self):
        """A dictionary of which contains the flag_library keys and a tuple
        containing the key's class object and a tuple of the offset sequence"""
        builder_dict = {
            'banners': (Banner, (1, 5, 3, 7)),
            'pubs': (Publication, ()),
            # 'revs':rev_gen(source, sentinals['revs']),
            #                 'inds':ind_gen(source, sentinals['inds']),
            #                 'scis':sci_gen(source, sentinals['scis']),
            #                 'pols':pol_gen(source, sentinals['pols']),
            'events': (Event, (1, 3, 5, 7)),
            'jobs': (Job, (1, 3, 5, 7, 9, 11, 13))
        }

        # for flag_type in self.flag_library:

    #             for flag_index in flag_type:
    #                 flag_dict[flag_type]

    def write_output(self):
        """Writes the properly formatted output to output.htm"""
        outfile = codecs.open(self._find_plaintext_directory + r'\output.htm',
                              'w',
                              'utf-8-sig',
                              'replace')
        out = [line + u'\n' for line in self.output]
        outfile.writelines(out)
        outfile.close()


class Article(object):
    """A subclass of Entry that provides a more specialized architecture for
    Publications, Industry News etc."""

    def __init__(self, date, title, summary, source, anchor_list,
                 link_list, name):
        """Initiate an Article instance"""
        assert len(anchor_list) == len(link_list), \
            'Anchor and Link lists unequal: ' + title
        for link in link_list:
            assert re.match(r'https?', link) is not None, \
                'URL Malformed: ' + title
        self.date = date
        self.title = title
        self.summary = summary
        self.source = source
        self.anchor_list = anchor_list
        self.link_list = link_list
        self.name = name

    # Assign Newsletter Type
    # call all newsletters of type, in last x days

    def lineout(self, newsletter, strip=False):
        """Defines a recursive function that builds a list that will become a
        Publication in the full Eloqua HTML"""

        temp_links = self.link_list
        temp_anchors = self.anchor_list

        # Should give a better explanation of this
        def recursive_string(links, anchors, newsletter):
            """A recursive function for adding all links and anchors in proper
            order"""

            core = [
                '<!-- ' + self.name + ' SECTION Start -->',
                '<a style="text-decoration: none" href="' +
                links[0] +
                '"><strong><font color="' +
                newsletter['primary_color'] +
                '" size="2" face="Arial">',
                '<!-- ' + self.name + ' TITLE-->' +
                self.title +
                '<!-- End --></font></strong></a><br><font color="' +
                newsletter['text_color'] +
                '" size="2" face="Arial">',
                '<!-- ' + self.name + ' CONTENT-->' +
                self.summary +
                ' [' +
                self.source +
                '] <!-- End --></font>' +
                '<a style="text-decoration: none" href="' +
                links[0] +
                '"><font color="' +
                newsletter['secondary_color'] +
                '" size="2" face="Arial"><strong>' +
                anchors[0] +
                '</strong></font></a>']

            if len(links) == 1:
                return core
            else:
                addon = [' <font color="' +
                         newsletter['secondary_color'] +
                         '" size="2" face="Arial"><strong>|</strong></font>',
                         ' <a style="text-decoration: none" href="' +
                         temp_links.pop(-1) +
                         '"><font color="' +
                         newsletter['secondary_color'] +
                         '" size="2" face="Arial"><strong>' +
                         temp_anchors.pop(-1) +
                         '</strong></font></a>']
                return recursive_string(links, anchors, newsletter) + addon

        br_add = recursive_string(temp_links, temp_anchors, newsletter)

        if not strip:
            br_add[-1] += '<br><br>'

        return br_add + ['<!-- ' + self.name + ' SECTION End -->']


class Publication(Article):
    """Subclass of Article. All Articles in the Publications Section go here"""

    def __init__(self, date, title, summary, source, anchor_list,
                 link_list, impact, division, topstory):
        """Initiating"""
        Article.__init__(self, date, title, summary, source, anchor_list,
                         link_list, '#PUBLICATIONS')
        self.impact = impact
        self.division = division
        self.topstory = topstory
        if 'Press release from' not in source:
            self.source = '<em>' + source + '</em>'

    # Perhaps this could be sorted by date
    def __lt__(self, other):
        """How Publications are sorted"""
        return self.impact < other.impact

    def __repr__(self):
        """Representation of publication"""
        return self.title

    def __str__(self):
        return self.title

    def lineout_top(self, newsletter):
        """A version of nl.lineout that strips <br><br> and replaces it
        with the Top Story border markup"""
        top_list = self.lineout(newsletter, strip=True)
        top_list[0] = '<!-- #TOPSTORY Start -->'
        del top_list[-1]
        top_list[-1] = (top_list[-1] +
                        ('</td></tr><tr><td style="padding-bottom: 15px; '
                         'border-bottom:1px solid; border-bottom-color: '
                         '#808080;">'))
        return top_list

    # set an if statement if IF already set
    def lookup_impact(self):
        """opens the impact factor CSV and checks a impact factorless article
        against the list of known impact factors. If the impact factor can't
        be called, it calls new_impact() to input a new entry"""
        with open(r'S:\CXN - Connexon\Connexogen\impactfactors.csv') as fin:
            csvin = csv.reader(fin)
            lookup = {row[0]: row for row in csvin}

        to_find = re.sub('</?em>', '', self.source)
        try:
            return float(lookup[to_find][2])
        except (KeyError, IndexError):
            print '[' + self.source + '] ' + self.title
            if self.anchor_list[0] == 'Press Release':
                in_name = raw_input('Input Publication Abbreviation: ')
            else:
                in_name = to_find
            in_issn = raw_input('Input ISSN: ')
            in_impact = raw_input('Input Impact Factor: ')
            new_impact(in_name, in_issn, in_impact)
            return float(in_impact)

        finally:
            fin.close()

    def set_impact(self, impact):
        """Sets the impact factor. Used when looking up impact factors from
        impact factor csv."""
        self.impact = impact


def new_impact(name, issn, impact):
    """Adds new impact factor information to the csv"""
    with open(r'S:\CXN - Connexon\Connexogen\impactfactors.csv', 'ab') as fin:
        if_sheet = csv.writer(fin)
        if_sheet.writerow((name, issn, impact))
        fin.close()


class Review(Publication):
    """A Review Publication. Contains author information"""

    def __init__(self, date, title, summary, source, anchor_list, link_list,
                 impact, authors):
        Article.__init__(self, date, title, summary, source, anchor_list,
                         link_list, '#REVIEWS')
        self.authors = authors
        self.impact = impact
        self.source = '<em>' + source + '</em>'

    def __lt__(self, other):
        """Sort by impact factor"""
        return self.impact < other.impact

    def __repr__(self):
        """Reviews are represented by titles"""
        return self.title

    def __str__(self):
        return self.title

    def archive(self, newsletter, volume, nl_date):
        """Provides HTML in Wordpress format"""
        volume_dash = re.sub(r'\.', '-', volume)
        date = time.strftime('%b %d', nl_date).replace(' 0', ' ')
        date_dash = date.replace(' ', '-')
        url = (newsletter['url'] +
               u'issue/volume-' +
               volume_dash +
               u'-' +
               date_dash +
               u'/">')
        out = [
            '<tr>',
            '<td class="reviewtitle"><a target="_blank" href="' +
            self.link_list[0] + '">' + self.title + '</a><br>' +
            self.authors + '</td>',
            '<td><em>' + self.source + '</em></a></td>',
            '<td>' + self.date + '</td>',
            '<td><a target="_blank" href="' + url + volume + ' | ' +
            date + '</a>' + '</td>',
            '</tr>',
            '']

        return out


class ScienceNews(Article):
    def __init__(self, date, title, summary, source, anchor_list, link_list):
        Article.__init__(self, date, title, summary, source, anchor_list,
                         link_list, '#SCIENCE')

    def __repr__(self):
        return self.title

    def __str__(self):
        return self.title


class IndustryNews(Article):
    def __init__(self, date, title, summary, source, anchor_list, link_list):
        Article.__init__(
            self,
            date,
            title,
            summary,
            source,
            anchor_list,
            link_list,
            '#INDUSTRY')

    def __repr__(self):
        return self.title

    def __str__(self):
        return self.title


class PolicyNews(Article):
    """Creates a Policy News article. This is similar to an Industry News
    article except for the <em> tags on the source and the use of 'Editorial'
    as opposed to 'Press Release'"""

    def __init__(self, date, title, summary, source, anchor_list, link_list):
        Article.__init__(
            self,
            date,
            title,
            summary,
            source,
            anchor_list,
            link_list,
            '#POLICY')

    def __repr__(self):
        return self.title

    def __str__(self):
        return self.title


class Banner(object):
    """A Banner object contains a Name, URL, Alt-Text and Image URL
    A Name is the internal reference used on the Connexon spreadsheet"""

    def __init__(self, name, url, text, img):
        self.name = name
        self.text = text
        self.url = url
        self.img = img

    def __repr__(self):
        return self.name

    def __str__(self):
        return (self.url + '<img border="0" alt="' + self.text + '" src="'
                + self.img + '" width="645" height="110"></a>')

    def banner_out(self, newsletter, issue, banner_number):
        """Formats a banner for use in a newsletter, appends all appropriate
        HTML to banner"""
        if banner_number == 1:
            append = 'i'
        elif banner_number == 2:
            append = 'ii'
        elif banner_number == 3:
            append = 'iii'
        else:
            append = '_mp'
            # need to revert back to 3 for the URL
            banner_number = 3
        return (
            ('<a style="text-decoration: none" href="'
             'http://secure.eloqua.com/e/f2.aspx?elqFormName=') +
            newsletter['name_short'] +
            str(banner_number) +
            '&elqSiteID=1832&e=<SPAN class=eloquaemail>EmailAddress</SPAN>&u=' +
            self.url +
            '&t=(A)' +
            newsletter['name_short'].upper() +
            issue +
            append +
            '"><img border="0" alt="' +
            self.text +
            '" src="' +
            self.img +
            '" width="645" height="110"></a>')

    def homebanner_out(self):
        """Formats banner in HTML to be placed in the Wordpress website"""
        return (
            ('<!--Banner Start--><div align="center">'
             '<a style="text-decoration: none" href="') +
            self.url + '"><img src="' + self.img + '" alt="' + self.text +
            '"></a></div><!--Banner End-->')


class TextBanner(object):
    """TextBanner Object"""

    def __init__(self, text, url):
        """Initiate Text Banner"""
        self.text = text
        self.url = url

    def text_massage(self, newsletter, issue):
        """Provides the Newsletter with a fully formatted Text Banner"""
        self.utm_replace(newsletter)
        stringer = self.text.split('strong>')
        stringer[0] = ('<font size="2" face="Arial" color="' +
                       newsletter['primary_color'] +
                       '">' + stringer[0])
        stringer[2] = ('<font size="2" face="Arial" color="' +
                       newsletter['text_color'] + '">' +
                       stringer[2])
        stringer[3] = ('<font size="2" face="Arial" color="' +
                       newsletter['primary_color'] + '">' +
                       stringer[3])
        textad = 'strong>'.join(stringer)
        textad += '</a>'
        return (
            '<a style="text-decoration: none" href="http://secure.eloqua.com/'
            'e/f2.aspx?elqFormName=' + newsletter['name_short'] +
            '3&elqSiteID=1832&e=<SPAN class=eloquaemail>EmailAddress</SPAN>' +
            '&u=' + self.url + '&t=(A)' + newsletter['name_short'].upper() +
            issue + 'iiitext">' + textad)

    def __repr__(self):
        """Returns text banner representation"""
        return self.text

    def __str__(self):
        """returns generalized TextBanner string"""
        return (self.url + '<font size="2" face="Arial" color="$primary">'
                + self.text + '</font></a>')

    def _seturl(self, url):
        """Sets the URL to a new string"""
        self.url = url

    def utm_replace(self, newsletter):
        """Replaces the generic 'cxn' with the current newsletter name"""
        self._seturl(re.sub(r'(\?utm_source=)\w+',
                            r'?utm_source=' + newsletter['name_short'],
                            self.url))
        return self.url


class Event(object):
    """An Event Entry, can be formatted for a newsletter or archive entry"""

    def __init__(self, title, link, date, location, name):
        self.title = title
        self.link = link
        self.date = date
        self.location = location
        self.name = '#EVENT'

    def __lt__(self, other):
        return self.date < other.date

    # Need single date as well
    def date_conversion(self):
        """Converts time strings of format "%Y-%m-%d" to "%B %d, %Y".
        Used to convert the archival format to newsletter format"""
        input_date_strs = self.date.split(' to ')

        if len(input_date_strs) == 1:
            date = time.strptime(input_date_strs[0], "%Y-%m-%d")
            return time.strftime("%B %d, %Y", date).replace(' 0', ' ')

        else:
            # use a list comprehension and tuple expansion
            start, end = [
                time.strptime(s, "%Y-%m-%d") for s in input_date_strs]

            # if both in the same year, omit it from start date
            start_fmt = "%B %d" if start.tm_year == end.tm_year else "%B %d, %Y"

            # if both in the same month and year, omit month from end date
            end_fmt = "%d, %Y" if (start.tm_mon, start.tm_year) == (end.tm_mon, end.tm_year) else "%B %d, %Y"

            return (time.strftime(start_fmt, start) +
                    '-' +
                    time.strftime(end_fmt, end)).replace(' 0', ' ').replace('-0', '-')

    def nl_location(self):
        """Generates a string from the event's city and country"""
        loc_list = self.location.split(', ')
        if len(loc_list) == 1 or len(loc_list) == 2:
            return self.location
        if len(loc_list) == 3:
            return ', '.join((loc_list[0], loc_list[2]))

    def arch_location(self):
        """Generates a string from the event's city and province/state"""
        loc_list = self.location.split(', ')
        if len(loc_list) == 1 or len(loc_list) == 2:
            return self.location
        if len(loc_list) == 3:
            return ', '.join((loc_list[0], loc_list[1]))

    def __repr__(self):
        return self.title

    def __str__(self):
        return self.title

    def nlout(self, newsletter):
        """Generates a list of lines to be included in a Newsletter"""
        if newsletter['name_short'] != 'hn':
            event = [
                '<!-- ' + self.name + ' SECTION Start -->',
                '<a style="text-decoration: none" href="' +
                self.link +
                '"><strong><font color="' +
                newsletter['primary_color'] +
                '" size="2" face="Arial">',
                '<!-- #EVENT TITLE--><font color="' +
                newsletter['secondary_color'] +
                '">NEW</font> ' +
                self.title +
                '<!-- End --></font></strong></a><br><font color="' +
                newsletter['text_color'] +
                '" size="2" face="Arial">',
                '<!-- #EVENT CONTENT-->' +
                self.date_conversion() +
                '<br>' +
                self.nl_location() +
                '<!-- End --><br><br>',
                '<!-- ' + self.name + ' SECTION End -->']
        else:
            event = [
                '<!-- ' + self.name + ' SECTION Start -->',
                '<a style="text-decoration: none" href="' +
                self.link +
                '"><strong><font color="' +
                newsletter['primary_color'] +
                '" size="2" face="Arial">',
                '<!-- #EVENT TITLE--><font color="#e36f1e">NEW</font> ' +
                self.title +
                '<!-- End --></font></strong></a><br><font color="' +
                newsletter['text_color'] +
                '" size="2" face="Arial">',
                '<!-- #EVENT CONTENT-->' +
                self.date_conversion() +
                '<br>' +
                self.nl_location() +
                '<!-- End --><br><br>',
                '<!-- ' + self.name + ' SECTION End -->']
        return event

    def archive(self):
        """Generates a list of lines to be printed in archiving"""
        return [
            u'<tr>',
            u'<td><a href="' +
            self.link +
            u'" target="_blank">' +
            self.title +
            u'</a></td>',
            u'<td>' +
            self.date +
            u'</td>',
            u'<td>' +
            self.arch_location() +
            u'</td>',
            u'</tr>',
            u'']


class Job(object):
    """A Job Entry"""
    name = '#JOB'

    def __init__(self, title, org, location, date, job_type, requirement,
                 link):
        self.title = title
        self.org = org
        self.location = location
        self.date = date
        self.job_type = job_type
        self.requirement = requirement
        self.link = link

    def __repr__(self):
        return self.title

    def __str__(self):
        return self.title

    def nlout(self, newsletter):
        """Creates newsletter ready text for a given job"""
        if newsletter['name_short'] != 'hn':
            job = [
                '<!-- ' + self.name + ' SECTION Start -->',
                '<a style="text-decoration: none" href="' +
                self.link +
                '"><strong><font color="' +
                newsletter['primary_color'] +
                '" size="2" face="Arial">',
                '<!-- #JOB TITLE--><font color="' +
                newsletter['secondary_color'] +
                '">NEW</font> ' +
                self.title +
                ' (' +
                self.org +
                ')',
                '<!-- End --></font></strong></a><br><br>',
                '<!-- ' + self.name + ' SECTION End -->']
        else:
            job = [
                '<!-- ' + self.name + ' SECTION Start -->',
                '<a style="text-decoration: none" href="' +
                self.link +
                '"><strong><font color="' +
                newsletter['primary_color'] +
                '" size="2" face="Arial">',
                '<!-- #JOB TITLE--><font color="#e36f1e">NEW</font> ' +
                self.title +
                ' (' +
                self.org +
                ')',
                '<!-- End --></font></strong></a><br><br>',
                '<!-- ' + self.name + ' SECTION End -->']
        return job

    def archive(self, newsletter):
        """Create HTML for Job archive"""
        out = [
            '<tr>',
            '<td><a href="' + self.link +
            ('" target="_blank"><span style="color: #2bb675;"><em>NEW </em>'
             '</span>') + self.title + '</a></td>',
            '<td>' + self.org + '</td>',
            '<td>' + self.job_type + '</td>',
            '<td>' + self.location + '</td>',
            '<td>' + self.requirement + '</td>',
            ('<td><a target="_blank" href="' + newsletter['url'] + '">' +
             newsletter['name_long'] + '</a></td>'),
            '<td>' + self.date + '</td>',
            '</tr>',
            '']

        return out

<file_sep>"""
Created on Aug 21, 2014

@author: memery
"""
import collections
import os
import time

import Connexogen


class Regulatory(object):
    def __init__(self, name, doc_number, link, agency):
        self.agency = agency
        self.name = name
        self.doc_number = doc_number
        self.link = link

    def _set_agency(self, agency):
        self.agency = agency

    def __repr__(self):
        if self.doc_number != '':
            return '[' + self.agency + '] ' + self.name + ' ' + '(FR Doc. No: ' + self.doc_number + ')'
        else:
            return '[' + self.agency + '] ' + self.name

    def __str__(self):
        if self.doc_number != '':
            return '[' + self.agency + '] ' + self.name + ' ' + '(FR Doc. No: ' + self.doc_number + ')'
        else:
            return '[' + self.agency + '] ' + self.name

    def lineout(self):
        if self.doc_number != '':
            return [
                '<!-- #' + self.agency + ' SECTION Start -->',
                ('<a style="text-decoration: none" href="' + self.link +
                 '"><strong><font color="#e36f1e" size="2" face="Arial">'),
                ('<!-- #' + self.agency + ' TITLE-->' + self.name +
                 ' (FR Doc. No: ' + self.doc_number +
                 ')<!-- End --></font></strong></a><br><br>'),
                '<!-- #' + self.agency + ' SECTION End -->']
        else:
            return [
                '<!-- #' + self.agency + ' SECTION Start -->',
                ('<a style="text-decoration: none" href="' + self.link +
                 '"><strong><font color="#e36f1e" size="2" face="Arial">'),
                ('<!-- #' + self.agency + ' TITLE-->' + self.name +
                 ' <!-- End --></font></strong></a><br><br>'),
                '<!-- #' + self.agency + ' SECTION End -->']

    def linebrstrip(self):
        if self.doc_number != '':
            return [
                '<!-- #' + self.agency + ' SECTION Start -->',
                ('<a style="text-decoration: none" href="' + self.link +
                 '"><strong><font color="#e36f1e" size="2" face="Arial">'),
                ('<!-- #' + self.agency + ' TITLE-->' + self.name +
                 ' (FR Doc. No: ' + self.doc_number +
                 ')<!-- End --></font></strong></a>'),
                '<!-- #' + self.agency + ' SECTION End -->']
        else:
            return [
                '<!-- #' + self.agency + ' SECTION Start -->',
                ('<a style="text-decoration: none" href="' + self.link +
                 '"><strong><font color="#e36f1e" size="2" face="Arial">'),
                ('<!-- #' + self.agency + ' TITLE-->' + self.name +
                 ' <!-- End --></font></strong></a>'),
                '<!-- #' + self.agency + ' SECTION End -->']


def ctn_main():
    source = Connexogen.sourcereader()
    # Make sure to change this later
    entries = ctn_entry_mapper(source[0], ctn_full_gen(source[0]))
    flags = ctn_flag_mapper(source[0], ctn_nl_flags(source[0]))

    out = []
    out.extend(header(flags))
    out.extend(menu(entries))
    out.extend(topstory(flags, entries))
    out.extend(publications(flags, entries))
    out.extend(reviews(flags, entries))
    out.extend(sciencenews(flags, entries))
    out.extend(policynews(flags, entries))
    out.extend(industrynews(flags, entries))
    out.extend(nih(entries))
    out.extend(cber(entries))
    out.extend(regulatory(entries))
    out.extend(eventsnl(flags, entries))
    out.extend(jobsnl(flags, entries))
    out.extend(footer())

    Connexogen.writetofile(out, source[1])
    Connexogen.wordpress(flags, entries, source[1])

    return out


def ctn_full_gen(source):
    """Creates a default dictionary that returns a tuple containing a
    sentinal string and all indices where that string appears"""
    query = {'>>-->>Banner 1 Name>>': 'banners',
             '>>-->>Banner 2 Name>>': 'banners',
             '>>-->>Banner 3 Name>>': 'banners',
             '>>-->>MP_Banner Name>>': 'banners',
             '>>-->>Text Banner Name>>': 'textbanner',
             '>>-->>Publication>>': 'pubs',
             '>>-->>Review>>': 'revs',
             '>>-->>Industry Title>>': 'inds',
             '>>-->>Science Title>>': 'scis',
             '>>-->>Policy Title>>': 'pols',
             '>>-->>NIH Title>>': 'regs',
             '>>-->>CBER Title>>': 'regs',
             '>>-->>Regulatory Title>>': 'regs',
             '>>-->>Event Title>>': 'events',
             '>>-->>Job Title>>': 'jobs'}

    line_count = 0
    sentinals = collections.defaultdict(list)
    for line in source:
        for cue in query:
            if cue in line:
                sentinals[query[cue]].append(line_count)
        line_count += 1

    return sentinals


def ctn_entry_mapper(source, sentinals):
    """A very important function. This function takes makes all the entries
    to their appropriate function and returns a dictionary of all entries in the
    newsletter"""
    func_map = {
        'banners': Connexogen.banner_gen(source, sentinals['banners']),
        'textbanner': Connexogen.textbanner_gen(source, sentinals['textbanner']),
        'pubs': Connexogen.pub_gen(source, sentinals['pubs']),
        'revs': Connexogen.rev_gen(source, sentinals['revs']),
        'inds': Connexogen.ind_gen(source, sentinals['inds']),
        'scis': Connexogen.sci_gen(source, sentinals['scis']),
        'pols': Connexogen.pol_gen(source, sentinals['pols']),
        'events': Connexogen.event_gen(source, sentinals['events']),
        'jobs': Connexogen.job_gen(source, sentinals['jobs']),
        'regs': reg_gen(source, sentinals['regs'])
    }

    return func_map


def reg_gen(source, indices):
    "Generates Regulatory entries from source"""
    regs = collections.defaultdict(list)

    for index in indices:
        if source[index + 1] != '':
            if 'NIH' in source[index]:
                reg = Regulatory(name=source[index + 1],
                                 doc_number=source[index + 3],
                                 link=source[index + 5],
                                 agency=u'NIH')
            elif 'CBER' in source[index]:
                reg = Regulatory(name=source[index + 1],
                                 doc_number='',
                                 link=source[index + 3],
                                 agency=u'CBER')
            else:
                reg = Regulatory(name=source[index + 1],
                                 doc_number=source[index + 3],
                                 link=source[index + 5],
                                 agency=source[index + 7])
            regs[reg.agency].append(reg)

    return regs


def ctn_nl_flags(source):
    """Creates a default dictionary that returns a tuple containing a
    sentinal string and all indices where that string appears"""
    query = {'>>-->>Newsletter Issue Number>>': 'issue',
             '>>-->>Newsletter Issue Date>>': 'date',
             # '>>-->>Subject Line>>':'subjectline',
             '>>-->>Homepage Banner Name>>': 'hpbanner',
             '>>-->>Connexon Banner Name>>': 'cxnbanner',
             '>>-->>Old Jobs>>': 'oldjobs',
             ">>-->>Insert last week's jobs' HTML here>>": 'prevjobs',
             '>>-->>end of plaintext>>-->>': 'end'}

    line_count = 0
    # should probably convert to a regular dictionary
    sentinals = collections.defaultdict(list)
    for line in source:
        for cue in query:
            if cue in line:
                sentinals[query[cue]].append(line_count)
        line_count += 1

    return sentinals


def ctn_flag_mapper(source, sentinals):
    """Maps the ctn_nl_flags sentinals to the appropriate function and stores that
    information in a dictionary. When creating a new function dependent on a
    flag, call it from here"""

    func_map = {
        'nl': ctn_info(),
        'issue': Connexogen.issue_number(source, sentinals['issue']),
        'date': Connexogen.issue_date(source, sentinals['date']),
        # 'subjectline':subjectline(source, sentinals['subjectline']),
        'hpbanner': Connexogen.homepagebanner(source, sentinals['hpbanner']),
        'cxnbanner': Connexogen.homepagebanner(source, sentinals['cxnbanner']),
        'oldjobs': Connexogen.job_grab(source, (sentinals['oldjobs'],
                                                sentinals['prevjobs'])),
        'prevjobs': Connexogen.job_grab(source, (sentinals['prevjobs'],
                                                 sentinals['end'])),
        'end': Connexogen.end_init()}

    return func_map


def ctn_info():
    return {
        'name_long': 'Cell Therapy News',
        'name_short': 'ctn',
        'primary_color': '#e36f1e',
        'secondary_color': '#003366',
        'text_color': '#666666',
        'header_image':
            ('http://img.en25.com/eloquaimages/clients/StemcellTech'
             'nologiesInc/%7B214e9670-0241-429d-8cfb-d1978ddcf8ae%'
             '7D_Header-BottomCorner.jpg'),
        'twitter_url': 'http://twitter.com/celltherapynews',
        'background_color': '',
        'footer_border_color': '',
        'footer_background_color': '',
        'division_list': (),
        'url': 'http://www.celltherapynews.com/'}


def sourcereader_test():
    """A simple version of sourcereader that is used in unit testing"""

    with open(r'C:\Users\memery\Documents\macro\macro\connexogen\ctn_plaintext_tester.txt', 'r') as source:
        outdir = os.path.dirname(source.name)
        source_list = []
        for line in source:
            line = line.decode('utf-8')
            line = line.strip('\n')
            source_list.append(line)

    source.close()

    return source_list, outdir


def header(flag_map):
    nl_issue = str(flag_map['issue'])
    nl_date = flag_map['date']
    out = [
        '<html>',
        '<head>',
        '<title>Newsletter Issue</title>',
        ('<style type="text/css">a:link {text-decoration: none; color:'
         '#e36f1e;}a:visited {text-decoration: none; color:#e36f1e;}a:active'
         ' {text-decoration: none; color:#e36f1e;}a:hover {text-decoration: '
         'underline; color:#e36f1e;}td {font-family: arial; font-size: '
         '12px; color: #666666;}</style>'),
        '</head>',
        '<body>',
        ('<table align="center" width="715" border="0" cellpadding="0" '
         'cellspacing="0"><tr><td width="100%" valign="top"><div align='
         '"right"><font color="#003366" size="1" face="arial">'),
        '<!-- #ISSUE Start -->',
        ('Issue ' + nl_issue + ' ' +
         time.strftime("%B %d, %Y", nl_date).replace(' 0', ' ')),
        '<!-- #ISSUE End-->',
        '',
        '</font></div>',
        ('<table width="715" cellspacing="0" cellpadding="0" border="0">'
         '<tbody><tr><td width="25" valign="top" bgcolor="#f89021" align='
         '"left" style="line-height:0;"><img width="16" height="14" border="0"'
         ' src="http://img.en25.com/eloquaimages/clients/Stemcell'
         'TechnologiesInc/%7B0117c1a8-0f84-4cfe-b19c-c18be7f47d4e%7D_Header-'
         'TopCorner.jpg"></td>'),
        '',
        '',
        '<td bgcolor="#f89021" valign="top" colspan="2" align="right">',
        '',
        '',
        ('<table border="0" cellspacing="0" cellpadding="0" width="100%" '
         'height="85"><tr><td height="85" valign="top" rowspan="2" width="205"'
         ' align="left"><a href="http://www.celltherapynews.com/" target="'
         '_blank"><img border="0" alt="Cell Therapy News - Your Industry in '
         'an Instant" src="http://img.en25.com/eloquaimages/clients/Stemcell'
         'TechnologiesInc/%7B8ad845f3-c815-42df-9bbb-eae2d1d8868a%7D_Header-'
         'Logo.gif" width="196" height="85"></a></td><td height="52" '
         'colspan="3" align="right">'),
        '',
        ('<img border="0" src="http://img.en25.com/eloquaimages/clients/'
         'stemcelltechnologiesinc/%7b188a1c2d-dd54-4c7b-8e9c-c8bec8dadd39%7d_'
         'header-circles.gif" width="215" height="52"></td></tr><tr><td '
         'height="33" valign="bottom" align="left">'),
        '<a href="http://www.celltherapynews.com/" target="_blank">',
        ('<img border="0" alt="Your Industry in an Instant" src="http://img.'
         'en25.com/eloquaimages/clients/stemcelltechnologiesinc/%7b35d54b1e-'
         'caf2-4402-8746-09ff65abbb71%7d_header-tagline-smaller.jpg" width='
         '"276" height="21"></a></td><td height="33" valign="bottom" align='
         '"right"><a href="http://twitter.com/celltherapynews" target="'
         '_blank">'),
        '',
        ('<img border="0" alt="Twitter" src="http://img.en25.com/eloquaimages/'
         'clients/stemcelltechnologiesinc/%7b8759c6c2-521e-48c1-9f19-'
         'a614a33e6faa%7d_header-twitter.gif" width="22" height="23"></a>'
         '&nbsp;&nbsp;<a href="http://www.facebook.com/CellTherapyNews" '
         'target="_blank">'),
        ('<img border="0" alt="Facebook" src="http://img.en25.com/eloquaimages'
         '/clients/stemcelltechnologiesinc/%7b57429e4a-4426-492b-a48a-67d20bd7'
         '87e1%7d_header-facebook.gif" width="22" height="24"></a></td>'),
        '<td width=20>&nbsp;</td></tr></table>',
        ('</td></tr><tr><td bgcolor="#f89021" height="10" colspan="3"></td>'
         '</tr><tr><td bgcolor="#ffe2c5" height="40" width="25"></td><td '
         'bgcolor="#ffe2c5" valign="middle" width="670" align="left"><table '
         'border="0" cellspacing="0" cellpadding="0" width="100%"><tr><td>'),
        '',
        ('<font style="font-size: 13px; font-weight: bold;" face="Arial" '
         'color="#e36f1e">'),
    ]

    return out


def menu(entry_map):
    """Creates the menu, will not produce science news or review links if
    you do not have any of those type of articles."""
    out = ['', '<!-- #MENU Start -->']
    html = ('<a style="text-decoration: none" href="#currentpublications">'
            '<font color="#e36f1e">Publications</font></a> | ')
    if len(entry_map['revs']) != 0:
        html = (html +
                '<a style="text-decoration: none" href="#reviews">'
                '<font color="#e36f1e">Reviews</font></a> | ')
    if len(entry_map['scis']) != 0:
        html = (html +
                '<a style="text-decoration: none" href="#sciencenews">'
                '<font color="#e36f1e">Science</font></a> | ')
    html = (html +
            '<a style="text-decoration: none" href="#policy">'
            '<font color="#e36f1e">Policy</font></a> | '
            '<a style="text-decoration: none" href="#business">'
            '<font color="#e36f1e">Business</font></a> | ')
    if 'NIH' in entry_map['regs']:
        html = (html +
                '<a style="text-decoration: none" href="#NIH">'
                '<font color="#e36f1e">NIH</font></a> | ')
    if 'CBER' in entry_map['regs']:
        html = (html +
                '<a style="text-decoration: none" href="#CBER">'
                '<font color="#e36f1e">CBER</font></a> | ')
    temp_keys = entry_map['regs'].keys()
    if 'NIH' in temp_keys:
        temp_keys.remove('NIH')
    if 'CBER' in temp_keys:
        temp_keys.remove('CBER')
    if len(temp_keys) == 1:
        html = (html +
                '<a style="text-decoration: none" href="#regulatory">'
                '<font color="#e36f1e">Regulatory</font></a> | ')
    html = (html +
            '<a style="text-decoration: none" href="#events">'
            '<font color="#e36f1e">Events</font></a> | '
            '<a style="text-decoration: none" href="#jobs">'
            '<font color="#e36f1e">Jobs</font></a>')
    out.extend((html,
                '<!-- #MENU End -->',
                '',
                ('</font></td></tr></table></td><td bgcolor="#ffe2c5" valign="'
                 'bottom" width="20" align="right" style="line-height:0;">'
                 '<img border="0" src="http://img.en25.com/eloquaimages/clients/'
                 'StemcellTechnologiesInc/%7B214e9670-0241-429d-8cfb-d1978ddcf8'
                 'ae%7D_Header-BottomCorner.jpg" width="15" height="15" style="'
                 'float:right;"></td></tr></tbody></table></td></tr><tr>'
                 '<td align="middle">'),
                ''))

    return out


def topstory(flag_map, entry_map):
    """Returns formatted Top Story as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    pubs = entry_map['pubs']
    banners = entry_map['banners']
    out = ['<!-- #TOPSTORY Start -->',
           ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
            '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
            'padding-bottom: 15px;" width="100%" height="20"><font color="'
            '#003366" face="Arial" size="2"><strong>TOP STORY</strong></font>'
            '</td></tr><tr><td style="padding-bottom: 15px;" width="100%">')]
    out.extend(pubs[0][0].lineout_top(newsletter))
    out.extend(
        ('',
         '<!-- #TOPSTORY BANNER Start-->',
         banners[0].banner_out(newsletter, nl_issue, 1),
         '<!-- #TOPSTORY BANNER End-->'))
    out.extend(('</td></tr></table>', '<!-- #TOPSTORY End -->', ''))
    return out


def publications(flag_map, entry_map):
    """Returns formatted Publications as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    pubs = entry_map['pubs']
    banners = entry_map['banners']

    out = [
        '<!-- #PUBLICATIONS Start --><a name="currentpublications"></a>',
        ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color='
         '"#003366" face="Arial" size="2"><strong>PUBLICATIONS (<a style="'
         'text-decoration: none" href="http://thomsonreuters.com/products_'
         'services/science/free/essays/impact_factor/"><font color="'
         '#003366">Ranked by impact factor of the journal</font></a>)'
         '</strong></font></td></tr><tr><td style="padding-bottom: 15px; '
         'border-bottom: 1px solid; border-bottom-color: silver;">')]

    for pub in pubs[1]:
        out.extend(pub.lineout(newsletter))
        out.append('')

    # Adds the second banner
    out.extend(
        ('<!-- #PUBLICATIONS BANNER Start-->',
         banners[1].banner_out(newsletter, nl_issue, 2),
         '<!-- #PUBLICATIONS BANNER End-->'))

    # Adds footer
    out.extend(
        ('</td></tr></table>',
         '<!-- #PUBLICATIONS End -->',
         '',
         ''))

    return out


def reviews(flag_map, entry_map):
    """Returns formatted Review Articles as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    revs = entry_map['revs']
    banners = entry_map['banners']

    out = [
        '<!-- #REVIEWS Start --><a name="reviews"></a>',
        ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr>'),
        ('<td style="padding-bottom: 15px;" width="100%" height="20">'
         '<font color="#003366" face="Arial" size="2"><strong>REVIEWS'
         '</strong></font></td></tr><tr><td style="padding-bottom: 15px; '
         'border-bottom: 1px solid; border-bottom-color: silver;">'),
        '']

    for rev in revs:
        out.extend(rev.lineout(newsletter))
        out.append('')

    out.extend(
        ('<font color="#666666" face="Arial" size="2">Visit our <a style="text-'
         'decoration: none" href="' + newsletter['url'] + 'reviews/?utm_source='
                                                          'newsletter&utm_medium=link&utm_campaign=' + newsletter[
             'name_short'] +
         'newsletterreviews"><font color="' + newsletter['primary_color'] +
         '"><strong>reviews page</strong></font></a> to see a complete list of'
         ' reviews in the cell, gene '
         'and immunotherapy research field.<br><br></font>', ''))

    out.extend(
        ('<!-- #REVIEWS BANNER Start-->',
         banners[2].banner_out(newsletter, nl_issue, 3),
         '<!-- #REVIEWS BANNER End-->'))

    out.extend(('</td></tr></table>', '<!-- #REVIEWS End -->', '', ''))

    return out


def sciencenews(flag_map, entry_map):
    """Returns formatted Science News articles as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    scis = entry_map['scis']
    banners = entry_map['banners']
    textbanner = entry_map['textbanner']

    out = [
        '<!-- #SCIENCE Start --><a name="sciencenews"></a>',
        ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20">'
         '<font color="#003366" face="Arial" size="2"><strong>SCIENCE NEWS'
         '</strong></font></td></tr><tr><td style="padding-bottom: 15px; '
         'border-bottom: 1px solid; border-bottom-color: silver;">'),
        '']

    for sci in scis:
        out.extend(sci.lineout(newsletter))
        out.append('')

    if len(banners) == 4:
        out.extend(
            ('<!-- #SCIENCE BANNER Start-->',
             banners[3].banner_out(newsletter, nl_issue, 4),
             '<!-- #SCIENCE BANNER End-->'))
    else:
        out.extend(('<!-- #SCIENCE BANNER Start-->',
                    textbanner.text_massage(newsletter, nl_issue),
                    '<!-- #SCIENCE BANNER End-->'))

    out.extend(('</td></tr></table>', '<!-- #SCIENCE End -->', '', ''))

    return out


def policynews(flag_map, entry_map):
    """Returns formatted Policy News articles as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    pols = entry_map['pols']
    banners = entry_map['banners']
    textbanner = entry_map['textbanner']
    out = [
        '<!-- #POLICY Start --><a name="policy"></a>',
        ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color="'
         '#003366" face="Arial" size="2"><strong>POLICY</strong></font></td>'
         '</tr><tr><td style="padding-bottom: 15px; border-bottom: 1px '
         'solid; border-bottom-color: silver;">'),
        '']

    for pol in pols[:-1]:
        out.extend(pol.lineout(newsletter))
        out.append('')
    if len(banners) == 4:
        out.extend(pols[-1].lineout(newsletter))
        out.extend(('<!-- #POLICY BANNER Start-->',
                    textbanner.text_massage(newsletter, nl_issue),
                    '<!-- #POLICY BANNER End-->'))
    else:
        out.extend(pols[-1].lineout(newsletter, strip=True))
    out.append('')

    out.extend(('</td></tr></table>', '<!-- #POLICY End -->', ''))

    return out


def industrynews(flag_map, entry_map):
    """Returns formatted Industry News articles a list"""
    newsletter = flag_map['nl']
    inds = entry_map['inds']
    out = [
        '<!-- #BUSINESS Start --><a name="business"></a>',
        ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color="'
         '#003366" face="Arial" size="2"><strong>BUSINESS</strong></font>'
         '</td></tr><tr><td style="padding-bottom: 15px; border-bottom: '
         '1px solid; border-bottom-color: silver;">'),
        '']

    for ind in inds[:-1]:
        out.extend(ind.lineout(newsletter))
        out.append('')

    out.extend(inds[-1].lineout(newsletter, strip=True))
    out.append('')

    out.extend(('</td></tr></table>', '<!-- #BUSINESS End -->', '', ''))

    return out


def nih(entry_map):
    regs = entry_map['regs']['NIH']
    out = ['<!-- #NIH Start --><a name="NIH"></a>',
           ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
            '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
            'padding-bottom: 15px;" width="100%" height="20"><font color="'
            '#003366" face="Arial" size="2"><strong>NIH</strong></font></td>'
            '</tr><tr><td style="padding-bottom: 15px; border-bottom: 1px '
            'solid; border-bottom-color: silver;">'),
           '']

    for reg in regs[:-1]:
        out.extend(reg.lineout())
        out.append('')

    out.extend(regs[-1].linebrstrip())
    out.append('')

    out.extend(('</td></tr></table>',
                '<!-- #NIH End -->',
                ''))

    return out


def cber(entry_map):
    regs = entry_map['regs']['CBER']
    out = ['<!-- #CBER Start --><a name="CBER"></a>',
           ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
            '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
            'padding-bottom: 15px;" width="100%" height="20"><font color="'
            '#003366" face="Arial" size="2"><strong>CBER</strong></font></td>'
            '</tr><tr><td style="padding-bottom: 15px; border-bottom: 1px '
            'solid; border-bottom-color: silver;">'),
           '']

    for reg in regs[:-1]:
        out.extend(reg.lineout())
        out.append('')

    out.extend(regs[-1].linebrstrip())
    out.append('')

    out.extend(('</td></tr></table>',
                '<!-- #CBER End -->',
                ''))

    return out


def regulatory(entry_map):
    regs = entry_map['regs']
    reg_dir = {
        'FDA': 'Food and Drug Administration (United States)',
        'EMA': 'European Medicines Agency (European Union)',
        'MHRA': 'Medicines and Healthcare Products Regulatory Agency',
        'TGA': 'Therapeutic Goods Administration'}

    out = ['<!-- #REGULATORY Start --><a name="regulatory"></a>',
           ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
            '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
            'padding-bottom: 15px;" width="100%" height="20"><font color="'
            '#003366" face="Arial" size="2"><strong>REGULATORY</strong></font>'
            '</td></tr><tr><td style="padding-bottom: 15px; border-bottom: 1px '
            'solid; border-bottom-color: silver;">')]
    ag_list = []

    for agency in regs.keys():
        if agency in reg_dir:
            ag_list.append(agency)

    for agency in ag_list[:-1]:
        out.extend(['<font color="#003366" face="Arial" size="2"><strong>' +
                    reg_dir[agency] + '</strong></font><br><br>',
                    ''])

        for reg in regs[agency]:
            out.extend(reg.lineout())
            out.append('')

    out.extend(['<font color="#003366" face="Arial" size="2"><strong>' +
                reg_dir[ag_list[-1]] + '</strong></font><br><br>',
                ''])

    for reg in regs[ag_list[-1]][:-1]:
        out.extend(reg.lineout())
        out.append('')

    out.extend(regs[ag_list[-1]][-1].linebrstrip())
    out.append('')

    out.extend(('</td></tr></table>',
                '<!-- #REGULATORY End -->',
                ''))

    return out


def eventsnl(flag_map, entry_map):
    """Returns formatted events as a list"""
    newsletter = flag_map['nl']
    events = entry_map['events']

    out = ['<!-- #EVENT Start --><a name="events"></a>',
           ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
            '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
            'padding-bottom: 15px;" width="100%" height="20"><font color="'
            '#003366" face="Arial" size="2"><strong>EVENTS</strong></font>'
            '</td></tr><tr><td style="padding-bottom: 15px; border-bottom: '
            '1px solid; border-bottom-color: silver;">'),
           '']

    for event in events:
        out.extend(event.nlout(newsletter))
        out.append('')

    out.extend(
        (('<font face="Arial" size="2" color="#666666">'
          'Visit our <a style="text-decoration: '
          'none" href="http://www.celltherapynews.com/events/?utm_source='
          'newsletter&utm_medium=link&utm_campaign=ctnnewsletterevents">'
          '<font color="#003366"><strong>events page</strong></font></a> to '
          'see a complete list of events in the cell, gene and immunotherapy '
          'community.</font>'),
         '</td></tr></table>',
         '<!-- #EVENT End -->',
         ''))

    return out


def jobsnl(flag_map, entry_map):
    """Returns formatted jobs as a list"""
    newsletter = flag_map['nl']
    prevjobs = flag_map['prevjobs']
    jobs = entry_map['jobs']

    out = ['<!-- #JOB Start --><a name="jobs"></a>',
           ('<table width="93%" border="0" cellspacing="0" cellpadding="0">'
            '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
            'padding-bottom: 15px;" width="100%" height="20"><font color="'
            '#003366" face="Arial" size="2"><strong>JOB OPPORTUNITIES</strong>'
            '</font></td></tr><tr><td style="padding-bottom: 15px;">'),
           '']

    for job in jobs:
        out.extend(job.nlout(newsletter))
        out.append('')

    out.extend(prevjobs)
    out.extend(
        ('',
         ('<br><font size="2" face="Arial" color="#666666"><a style="text-'
          'decoration: none" href="http://connexoncreative.com/job/?utm_source='
          'newsletter&utm_medium=link&utm_campaign=' + newsletter['name_short'] +
          'newslettersubmitjobs"><font color="' + newsletter['primary_color'] +
          '"><strong>Recruit Top Talent</strong></font></a>: Reach more than '
          '50,000 potential candidates by <a href="http://connexoncreative.com/'
          'job/?utm_source=newsletter&utm_medium=link&utm_campaign=' +
          newsletter['name_short'] + 'newslettersubmitjobs"><strong><font color="' +
          newsletter['primary_color'] + '"><u>posting</u></font></strong></a>'),
         (' your organization\'s career opportunities on the Connexon Creative '
          '<a href="http://connexoncreative.com/jobs/?utm_source=newsletter&utm'
          '_medium=link&utm_campaign=' + newsletter['name_short'] + 'newsletterjobs"><strong>'
                                                                    '<font color="' + newsletter[
              'primary_color'] + '"><u>Job Board</u></font></strong></a>'
                                 ' at no cost.'),
         '</font></td></tr></table>',
         '<!-- #JOB End -->',
         ''))

    return out


def footer():
    out = [
        '<!-- #FOOTER Start -->',
        ('<br></td></tr><tr><td width="100%" valign="top"><div align="center">'
         '<table width="715" cellspacing="0" cellpadding="0" border="0" '
         'style="float:left;"><tbody><tr><td width="25" valign="top" '
         'bgcolor="#ffe2c5" align="left" style="height: 40px; line-height:0;">'
         '<img width="13" height="13" border="0" src="http://img.en25.com/'
         'eloquaimages/clients/StemcellTechnologiesInc/%7Bd24e7bcc-00c8-'
         '45b3-bc7e-714c8f097275%7D_Footer-TopCorner.jpg"></td>'),
        ('<td bgcolor="#ffe2c5" align="left"><font size="2" face="arial" '
         'color="#005581"><strong>SUBSCRIBER TOOLS:</strong></font></td>'
         '<td valign="middle" bgcolor="#ffe2c5" align="right" style="text-'
         'align:right;"><a target="_blank" href="http://www.connexoncreative'
         '.com/subscription/?email=<span class=eloquaemail>EmailAddress'
         '</span>"><img width="104" height="20" border="0" src="http://img.'
         'en25.com/eloquaimages/clients/StemcellTechnologiesInc/%7B37a164a1-'
         'e0c8-49ed-b729-430daa18f0e5%7D_Footer-Subscribe.jpg" alt='
         '"Subscribe"></a>'),
        '<a target="_blank" href="http://www.celltherapynews.com/archives/">',
        ('<img width="103" height="20" border="0" src="http://img.en25.com/'
         'eloquaimages/clients/StemcellTechnologiesInc/%7B07d62e04-14e3-4673-'
         '970d-a07eb9ecdb1e%7D_Footer-Archives.jpg" alt="Archives"></a>    '
         '<a target="_blank" href="http://twitter.com/celltherapynews">'),
        ('<img width="27" height="27" border="0" src="http://img.en25.com/'
         'eloquaimages/clients/StemcellTechnologiesInc/%7B9f944301-ed95-42ab-'
         '95ab-d810a3630148%7D_Header-Twitter.jpg" alt="Twitter"></a>  '
         '<a target="_blank" href="http://www.facebook.com/CellTherapyNews">'
         '<img width="26" height="27" border="0" src="http://img.en25.com/'
         'eloquaimages/clients/StemcellTechnologiesInc/%7Bf961867c-1b7a-4426-'
         '8fd0-0c61f1898fe6%7D_Header-Facebook.jpg" alt="Facebook"></a></td>'
         '<td bgcolor="#ffe2c5"> </td></tr><tr><td bgcolor="#f89021" '
         'align="left" colspan="2" style="line-height:0;">'),
        ('<img width="123" height="43" border="0" src="http://img.en25.com/'
         'eloquaimages/clients/StemcellTechnologiesInc/%7Bdc45feb5-fb9e-4fde-'
         'bf04-a8e4c400093e%7D_Footer-Circles.gif"></td>'),
        ('<td bgcolor="#f89021" align="right" style="text-align:right;"><font '
         'color="#ffffff"><a target="_blank" href="http://www.connexoncreative'
         '.com/subscription/?email=<span class=eloquaemail>EmailAddress'
         '</span>" style="text-decoration: none"><font size="2" face="arial" '
         'color="#ffffff" style="font-weight: bold">Profile Center</font></a>'),
        ('  |  <a target="_blank" href="http://www.connexoncreative.com" '
         'style="text-decoration: none"><font size="2" face="arial" '
         'color="#ffffff" style="font-weight: bold">Connexon Publications'
         '</font></a>'),
        ('  |  <a target="_blank" href="http://www.connexoncreative.com/'
         'publication/" style="text-decoration: none"><font size="2" '
         'face="arial" color="#ffffff" style="font-weight: bold">Article '
         'Submission</font></a>  |  <a target="_blank" '
         'href="http://connexoncreative.com/contact-us/" '
         'style="text-decoration: none">'),
        ('<font size="2" face="arial" color="#ffffff" style="font-weight: '
         'bold">Contact Us</font></a></font></td><td width="20" valign='
         '"bottom" bgcolor="#f89021" align="right" style="line-height:0; '
         'text-align:right;"><img width="13" height="15" border="0" src="'
         'http://img.en25.com/eloquaimages/clients/StemcellTechnologiesInc/'
         '%7B190374c8-37fe-445f-abc3-96e9a1cd0c6a%7D_Footer-BottomCorner.jpg">'
         '</td></tr></tbody></table></div>'),
        '<!-- #FOOTER End -->',
        '',
        '</td></tr></table>',
        '</body></html>']

    return out


if __name__ == "__main__":
    tester = ctn_main()
    Connexogen.writetofile(tester, r'C:\Users\memery\Documents\macro\macro\connexogen\\')

# BUG: CXN Banner does not appear
# TODO: Integrate archival function
# TODO: Reviews don't sort
# BUG: Can't not have CBER
<file_sep>'''
This module holds functions that contain a large amount of data that will not
be modified (e.g. the Newsletter or Textad info).
'''
from ConnexogenClasses import TextBanner

def newsletter_info(newsletter):
    """Retrieves the newsletter information in dictionary format based on
    the newsletter's short name (e.g. 'esc')"""
    info = {
        'cscn': {
            'name_long': 'Cancer Stem Cell News',
            'name_short': 'cscn',
            'primary_color': '#0096d6',
            'secondary_color': '#8dc63f',
            'text_color': '#000000',
            'header_image': ('http://img.en25.com/EloquaImages/clients/'
             'StemcellTechnologiesInc/{79506c2c-f80b-41be-b7bf-734393b1f1b6}'
             '_NewsletterEmHeader_CSCN.png'),
            'twitter_url': 'http://twitter.com/cancerscnews',
            'background_color': '#cccccc',
            'footer_border_color': '#0096d6',
            'footer_background_color': '#dddddd',
            'division_list': (),
            'url': 'http://www.cancerstemcellnews.com/'},
        'cbn': {
            'name_long': 'Cord B<NAME>',
            'name_short': 'cbn',
            'primary_color': '#bc8d0a',
            'secondary_color': '#c41230',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{d6fd8fee-0a6f-46b4-8f78-e61e09b8947e}'
             '_NewsletterEmHeader_CBN.png'),
            'twitter_url': 'http://twitter.com/Cord_Blood_News',
            'background_color': '#fbe6ad',
            'footer_border_color': '#666666',
            'footer_background_color': '#fdf6e2',
            'division_list': (),
            'url': 'http://www.cordbloodresearchnews.com/'},
        'ecm': {
            'name_long': 'Extracellular Matrix News',
            'name_short': 'ecm',
            'primary_color': '#91278f',
            'secondary_color': '#6cb33f',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{ca3ccc30-2caa-48bb-bddd-ba92c80b981c}'
             '_NewsletterEmHeader_ECM.png'),
            'twitter_url': 'http://twitter.com/ExtracellMatrix',
            'background_color': '#cccccc',
            'footer_border_color': '#91278f',
            'footer_background_color': '#dddddd',
            'division_list': (),
            'url': 'http://www.extracellularmatrixnews.com/'},
        'hin': {
            'name_long': 'Human Immunology News',
            'name_short': 'hin',
            'primary_color': '#5d245a',
            'secondary_color': '#765dc6',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{1431f70f-ebb9-455c-84f1-2fbcac72b7d7}'
             '_NewsletterEmHeader_HIN.png'),
            'twitter_url': 'http://twitter.com/humanimmunenews',
            'background_color': '#cccccc',
            'footer_border_color': '#5d245a',
            'footer_background_color': '#dddddd',
            'division_list': (),
            'url': 'http://www.humanimmunologynews.com/'},
        'irn': {
            'name_long': 'Immune Regulation News',
            'name_short': 'irn',
            'primary_color': '#4f2683',
            'secondary_color': '#009fc2',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{f9995aac-ea5c-41f2-ba83-5ebb839427cd}'
             '_NewsletterEmHeader_IRN.png'),
            'twitter_url': 'http://twitter.com/Immune_News',
            'background_color': '#cccccc',
            'footer_border_color': '#4f2683',
            'footer_background_color': '#dddddd',
            'division_list': (),
            'url': 'http://www.immuneregulationnews.com/'},
        'iidn': {
            'name_long': 'Immunology of Infectious Disease News',
            'name_short': 'iidn',
            'primary_color': '#512698',
            'secondary_color': '#765dc6',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{5aa8e6c6-5073-453b-8afa-40cd6ca59ffa}'
             '_NewsletterEmHeader_IIDN.png'),
            'twitter_url': 'http://twitter.com/infdisease_news',
            'background_color': '#cccccc',
            'footer_border_color': '#512698',
            'footer_background_color': '#dddddd',
            'division_list': ('',
             'HIV'),
            'url': 'http://www.immunologyofinfectiousdiseasenews.com/'},
        'mcn': {
            'name_long': 'Mammary Cell News',
            'name_short': 'mcn',
            'primary_color': '#006699',
            'secondary_color': '#f8981d',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{adc50aa8-9287-454e-a2a3-ac4ef53d77ca}'
             '_NewsletterEmHeader_MCN.png'),
            'twitter_url': 'http://twitter.com/MammaryCell',
            'background_color': '#b8b8b8',
            'footer_border_color': '#006699',
            'footer_background_color': '#cccccc',
            'division_list': ('LABORATORY RESEARCH',
             'CLINICAL RESEARCH'),
            'url': 'http://www.mammarycellnews.com/'},
        'mescn': {
            'name_long': 'Mesenchymal Cell News',
            'name_short': 'mescn',
            'primary_color': '#004813',
            'secondary_color': '#e36f1e',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{b9f69ff7-263d-4283-aee6-b15488206cc4}'
             '_NewsletterEmHeader_MESCN.png'),
            'twitter_url': 'http://twitter.com/MesenchymalCell',
            'background_color': '#b8b8b8',
            'footer_border_color': '#004813',
            'footer_background_color': '#dddddd',
            'division_list': (),
            'url': 'http://www.mesenchymalcellnews.com/'},
        'esc': {
            'name_long': 'ESC & iPSC News',
            'name_short': 'esc',
            'primary_color': '#3366ff',
            'secondary_color': '#ff9900',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{c3e1525d-7e28-472b-90fe-2254d6bbd7ba}'
             '_NewsletterEmHeader_ESC.png'),
            'twitter_url': 'http://twitter.com/ESC_iPSC_News',
            'background_color': '#b8b8b8',
            'footer_border_color': '#666666',
            'footer_background_color': '#cccccc',
            'division_list': (),
            'url': 'http://www.escellnews.com/'},
        'ncn': {
            'name_long': 'Neural Cell News',
            'name_short': 'ncn',
            'primary_color': '#00853f',
            'secondary_color': '#ff6600',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{e3376acd-afea-4df8-8f89-e098e1ccaa67}'
             '_NewsletterEmHeader_NCN.png'),
            'twitter_url': 'http://twitter.com/NeuralCell',
            'background_color': '#b8b8b8',
            'footer_border_color': '#666666',
            'footer_background_color': '#dddddd',
            'division_list': (),
            'url': 'http://www.neuralcellnews.com/'},
        'pacn': {
            'name_long': 'Pancreatic Cell News',
            'name_short': 'pacn',
            'primary_color': '#e36f1e',
            'secondary_color': '#a25018',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{82e32703-bd89-4603-ba3d-3fcf5f32564b}'
             '_NewsletterEmHeader_PACN.png'),
            'twitter_url': 'http://twitter.com/PancreaticCell',
            'background_color': '#cccccc',
            'footer_border_color': '#e36f1e',
            'footer_background_color': '#dddddd',
            'division_list': ('DIABETES & PANCREATITIS',
             'PANCREATIC CANCER'),
            'url': 'http://www.pancreaticcellnews.com/'},
        'pcn': {
            'name_long': 'Prostate Cell News',
            'name_short': 'pcn',
            'primary_color': '#0055a4',
            'secondary_color': '#e36f1e',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{4900c798-bfa4-4776-9ce7-fafd716040e0}'
             '_NewsletterEmHeader_PCN.png'),
            'twitter_url': 'http://twitter.com/ProstateCell',
            'background_color': '#e8e8e8',
            'footer_border_color': '#0055a4',
            'footer_background_color': '#dddddd',
            'division_list': ('LABORATORY RESEARCH',
             'CLINICAL RESEARCH'),
            'url': 'http://www.prostatecellnews.com/'},
        'pulcn': {
            'name_long': 'Pulmonary Cell News',
            'name_short': 'pulcn',
            'primary_color': '#5d245a',
            'secondary_color': '#98012e',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{32370387-17b3-46a9-a784-880a31a7b19f}'
             '_NewsletterEmHeader_PULCN.png'),
            'twitter_url': 'http://twitter.com/pulmonary_news',
            'background_color': '#cccccc',
            'footer_border_color': '#5d245a',
            'footer_background_color': '#dddddd',
            'division_list': ('',
             'LUNG CANCER'),
            'url': 'http://www.pulmonarycellnews.com/'},
        'hn': {
            'name_long': '<NAME>',
            'name_short': 'hn',
            'primary_color': '#990033',
            'secondary_color': '#69321f',
            'text_color': '#000000',
            'header_image':
            ('http://img.en25.com/EloquaImages/clients/StemcellTechnologiesInc/'
             '{c3621d49-7491-408f-93a3-1f2692fc9915}'
             '_NewsletterEmHeader_HN.png'),
            'twitter_url': 'http://twitter.com/Hema_News',
            'background_color': '#cccccc',
            'footer_border_color': '#990033',
            'footer_background_color': '#dddddd',
            'division_list': ('',
             'CLINICAL RESEARCH'),
            'url': 'http://www.hematopoiesisnews.com/'}}
    return info[newsletter]


def get_textbanner(text_banner_name):
    """Return a textbanner based solely on it's name as it appears in
    advertising schedule. Default utm_source is cxn"""

    text_banners ={
    'HIP_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong><br> View immunology lectures, '
         'protocols and other resources on the </font><strong><em>Human '
         'Immunology Portal</em>.</strong>'),
        ('http://www.humanimmunologyportal.com/?utm_source=cxn%26utm_medium='
         'link%26utm_campaign=hipgeneral')),
    'HIV_wallchart_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong> Free <em>Nature Reviews Immunology'
         '</em> poster - Immune Response to HIV.</font><strong> Request a copy'
         '.</strong>'),
        ('http://www.stemcell.com/Home/Forms/Wallcharts/Wallchart%20Immune%20'
         'Response%20to%20HIV.aspx?utm_source=cxn%26utm_medium=link%26utm_'
         'campaign=cshivposter')),
    'HIV_profiles_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong> Learn how <em>ex vivo</em> models '
         'drive progress in HIV research. </font><strong>Read the research '
         'profiles.</strong>'),
        ('http://www.stemcell.com/en/Pages/HIV-Case-Studies.aspx?utm_source='
         'cxn%26utm_medium=link%26utm_campaign=hivresearchprofiles')),
    'Mouse_hema_wallchart_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong> Free mouse hematopoietic '
         'progenitors wallchart. </font><strong>Request your copy.</strong>'),
        ('http://www.stemcell.com/Home/Forms/Wallcharts/Wallchart%20Mouse%20'
         'Hematopoietic%20Progenitors.aspx?id={16CC3A92-DE41-46B0-A84C-'
         '7AD83E7F8CB3}%26utm_source=cxn%26utm_medium=link%26utm_campaign='
         'MethoCultWallchart')),
    'Human_hema_wallchart_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong> Free human hematopoietic '
         'progenitors wallchart.</font><strong> Request your copy.</strong>'),
        ('http://www.stemcell.com/Home/Forms/Wallcharts/Wallchart%20Human%20'
         'Hematopoietic%20Progenitors.aspx?id={6B493CC5-5E99-45AF-A607-'
         '7476868E88C0}%26utm_source=cxn%26utm_medium=link%26utm_campaign='
         'ON225-HemaHumanWallchart_645x110')),
    'Mesenchymal_wallchart_CXN_textad':TextBanner(
        ('<strong>New wallchart from our sponsor:</strong><br> Mesenchymal Stem'
         ' Cells (a <em>Nature Reviews Molecular Cell Biology</em> '
         'collaboration).</font><strong>Request your free copy.</strong>'),
        ('http://www.stemcell.com/forms/wallcharts/wallchart-mesenchymal-stem-'
         'cells?utm_source=cxn%26utm_medium=link%26utm_campaign='
         'naturemscwallchart_645x110 ')),
    'Neural_wallchart_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong> Free wallchart from <em>Nature '
         'Neuroscience</em> - Neural Stem Cells. </font><strong>Request your '
         'copy.</strong>'),
        ('http://www.stemcell.com/Home/Forms/Wallcharts/Wallchart Neural Stem '
         'Cells.aspx?utm_source=cxn%26utm_medium=link%26utm_campaign='
         'NeuralWallchart_645x110-RequestWallchart')),
    'Regen_Med_Wallchart_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong> Pluripotent cell isolation for '
         'regenerative medicine.</font> <strong>Request a free wallchart from '
         '<em>Nature</em>.</strong>'),
        ('http://www.stemcell.com/Home/Forms/Wallcharts/Wallchart%20Pluripotent'
         '%20Stem%20Cell%20Biology.aspx?utm_source=cxn%26utm_medium=link%26'
         'utm_campaign=PluriWall_645x110')),
    'Cord_blood_techbull_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong> Learn about assays for cord blood.'
         ' </font><strong>Download the free technical bulletin.</strong>'),
        ('http://www.stemcell.com/en/Technical-Resources/228ae/29331-The-CFC-'
         'Assay-For-Cord-Blood.aspx?utm_source=cxn%26utm_medium=link%26utm_'
         'campaign=ON218-CordBloodTechBull_645x110')),
    'hESC_iPSC_webinar_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong><br> Learn About Groundbreaking '
         'Applications for Feeder-Free hESC & hiPSC Culture. </font><strong>'
         'Watch Webinar Now</strong>'),
        ('http://www.stemcell.com/en/Technical-Resources/0009e/Groundbreaking-'
         'Applications-of-Feeder-Free-hESC-hiPSC-Culture.aspx?utm_source=cxn'
         '%26utm_medium=link%26utm_campaign=recordedwebinar_mtesr1applications'
         '_645x110')),
    'ALDEFLUOR_vid_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong><br> Looking for ALDH<sup>+</sup> '
         'cancer stem cells? </font><strong>Watch a video to see how '
         'ALDEFLUOR&trade; can help.</strong>'),
        ('http://www.stemcell.com/en/Technical-Resources/c9294/ALDEFLUOR-Detect'
         '-normal-and-cancer-precursor-cells.aspx?utm_source=cxn%26utm_medium='
         'link%26utm_campaign=aldefluorquickvid')),
    'Mamary_wallchart_CXN_textad':TextBanner(
        ('<strong>From our sponsor:</strong><br> Interested in assays for human'
         ' mammary stem and progenitor cells? </font><strong>Request your free'
         ' wallchart.</strong>'),
        ('http://www.stemcell.com/en/Forms/Wallcharts/Wallchart-Assays-for-'
         'Human-Mammary-Stem-and-Progenitor-Cells.aspx?utm_source=cxn%26utm_'
         'medium=link%26utm_campaign=%09ON107-MammaryWallchart-645x110_CTA_'
         'RequestYH'))
       }
    return text_banners[text_banner_name]
<file_sep># -*- coding: utf-8 -*-
"""
The Connexogen Module generates a fully formed HTML Connexon Newsletter from
an appropriate a properly formatted text file"""
import Tkinter
import tkFileDialog
import os
import codecs
import collections
import shutil
import re
import time
import csv

from ConnexogenRetrieval import newsletter_info, get_textbanner
from ConnexogenClasses import Job, Event, \
    Banner, PolicyNews, Publication, ScienceNews, Review, IndustryNews


def foi(newsletter):
    """Field of interest. changes the '_____ community' sentence at the
    bottom of publications and events"""
    # Regex expression. Note that string.strip could strip the 's' off of
    # 'Hematopoiesis'
    field = re.sub(' News', '', newsletter['name_long'])

    # ESC & iPSC are always capitalized
    if newsletter['name_short'] != 'esc':
        field = field.lower()
    return field


def full_gen(source):
    """Creates a default dictionary that returns a tuple containing a
    sentinal string and all indices where that string appears"""
    query = {'>>-->>Banner 1 Name>>': 'banners',
             '>>-->>Banner 2 Name>>': 'banners',
             '>>-->>MP_Banner Name>>': 'banners',
             '>>-->>Text Banner Name>>': 'textbanner',
             '>>-->>Publication>>': 'pubs',
             '>>-->>Review>>': 'revs',
             '>>-->>Industry Title>>': 'inds',
             '>>-->>Science Title>>': 'scis',
             '>>-->>Policy Title>>': 'pols',
             '>>-->>Event Title>>': 'events',
             '>>-->>Job Title>>': 'jobs',
    }

    line_count = 0
    sentinals = collections.defaultdict(list)
    for line in source:
        for cue in query:
            if cue in line:
                sentinals[query[cue]].append(line_count)
        line_count += 1

    return sentinals


def entry_mapper(source, sentinals):
    """A very important function. This function takes makes all the entries
    to their appropriate function and returns a dictionary of all entries in the
    newsletter"""
    func_map = {
        'banners': banner_gen(source, sentinals['banners']),
        'textbanner': textbanner_gen(source,
                                     sentinals['textbanner']),
        'pubs': pub_gen(source, sentinals['pubs']),
        'revs': rev_gen(source, sentinals['revs']),
        'inds': ind_gen(source, sentinals['inds']),
        'scis': sci_gen(source, sentinals['scis']),
        'pols': pol_gen(source, sentinals['pols']),
        'events': event_gen(source, sentinals['events']),
        'jobs': job_gen(source, sentinals['jobs'])}

    return func_map


def pub_gen(source, indices):
    """Generates list of Publications from source"""
    top = []
    div1 = []
    div2 = []
    pubs = []

    for index in indices:
        if source[index + 8] != '':

            # splits the anchor and link list strings into lists
            anchor_list = source[index + 14].split(', ')
            link_list = source[index + 16].split(', ')
            topstory = False
            if source[index + 4] == 'Y':
                topstory = True
            pub = Publication(
                source[index + 2],
                source[index + 8],
                source[index + 10],
                source[index + 12],
                anchor_list,
                link_list,
                source[index + 6],  # Impact Factor
                source[index + 18],
                topstory)
            if pub.topstory or anchor_list[0] == 'Press Release':
                pub.set_impact(100)
            elif pub.impact == '':
                pub.set_impact(pub.lookup_impact())
            else:
                pub.set_impact(float(pub.impact))
            if topstory:
                top.extend([pub])
            elif pub.division == '1' or pub.division == '':
                div1.extend([pub])
            elif pub.division == '2':
                div2.extend([pub])
    div1.sort(reverse=True)
    div2.sort(reverse=True)

    # if Top Story section is empty then pop the highest impact publication
    # from div1
    if not top:
        story = div1.pop(0)
        top.append(story)
    assert (len(top) == 1), "More than one top story!"
    pubs.extend([top])
    pubs.extend([div1])
    pubs.extend([div2])

    return pubs


def banner_gen(source, indices):
    """Generates banners from Source"""
    banners = []

    for index in indices:
        if source[index + 3] != '':
            banner = Banner(
                source[index + 1],
                source[index + 5],
                source[index + 3],
                source[index + 7])
            banners.append(banner)

    return banners


def textbanner_gen(source, index):
    return get_textbanner(source[index[0] + 1])


def contestbanner_gen():
    """Provide Contest Banner.I haven't seen one in a while so it hasn't been
    implemented"""
    print 'Not implemented yet!'


# All generators after pub_gen are less complicated versions of that generator
# It may be worth it to actually have all objects feed through a single generator
def rev_gen(source, indices):
    """Generates Review articles from source"""
    revs = []

    for index in indices:
        if source[index + 6] != '':
            anchor_list = source[index + 14].split(', ')
            link_list = source[index + 16].split(', ')
            rev = Review(
                source[index + 12],
                source[index + 4],
                source[index + 6],
                source[index + 8],
                anchor_list,
                link_list,
                source[index + 2],
                source[index + 10])
            if rev.impact == '':
                rev.lookup_impact()
            else:
                rev.set_impact(float(rev.impact))
            revs.extend([rev])
    revs.sort(reverse=True)

    return revs


def sci_gen(source, indices):
    """Generates Science News articles from source"""
    scis = []

    for index in indices:
        if source[index + 1] != '':
            sci = ScienceNews(None,
                              source[index + 1],
                              source[index + 3],
                              source[index + 5],
                              ['Press Release'],
                              [source[index + 7]])
            scis.extend([sci])

    return scis


def ind_gen(source, indices):
    """Generates Industry News articles from source"""
    inds = []

    for index in indices:
        if source[index + 1] != '':
            if source[index + 9] == '':
                anchors = ['Press Release']
            else:
                anchors = source[index + 9].split(', ')
            ind = IndustryNews(None, source[index + 1], source[index + 3],
                               source[index + 5], anchors, [source[index + 7]])
            inds.extend([ind])

    return inds


def pol_gen(source, indices):
    """Generates Policy News articles from source"""
    pols = []

    for index in indices:
        if source[index + 1] != '':
            pol = PolicyNews(None,
                             source[index + 1],
                             source[index + 3],
                             '<em>' + source[index + 5] + '</em>',
                             ['Editorial'],
                             [source[index + 7]])
            pols.extend([pol])

    return pols


def event_gen(source, indices):
    """Generates events from source"""
    events = []

    for index in indices:
        if source[index + 1] != '':
            event = Event(title=source[index + 1],
                          link=source[index + 3],
                          date=source[index + 5],
                          location=source[index + 7],
                          name='#EVENT')
            events.extend([event])
    events.sort()

    return events


def job_gen(source, indices):
    "Generates jobs from source"""
    jobs = []

    for index in indices:
        if source[index + 1] != '':
            job = Job(title=source[index + 1],
                      org=source[index + 3],
                      location=source[index + 5],
                      date=source[index + 7],
                      job_type=source[index + 9],
                      requirement=source[index + 11],
                      link=source[index + 13])
            jobs.extend([job])

    return jobs


def sourcereader():
    """Creates a file dialog so that you may select the appropriate
    newsletter"""

    # Calls an Tkinter UI object then immediately hides it
    # Need to do this for tkFileDialog
    root = Tkinter.Tk()
    root.withdraw()

    source = tkFileDialog.askopenfile(
        parent=root,
        initialdir=r"S:\CXN - Connexon\CXN Publications",
        title="Select Plaintext")
    outdir = os.path.dirname(source.name)
    source_list = []
    for line in source:
        line = line.decode('utf-8')
        line = line.strip('\n')
        source_list.append(line)

    source.close()

    assert '>>-->>Newsletter Name>>' in source_list[0], \
        'You have not selected a Connexon template textfile.'

    return source_list, outdir


def sourcereader_test():
    """A simple version of sourcereader that is used in unit testing"""

    with open(
            r'S:\CXN - Connexon\CXN Publications\Extracellular Matrix News\Text Versions\''
            r'Extracellular Matrix News 5.XX (2014)\ECM 5.30.htm',
            'r') as source:
        outdir = os.path.dirname(source.name)
        source_list = []
        for line in source:
            line = line.decode('utf-8')
            line = line.strip('\n')
            source_list.append(line)

    source.close()

    return source_list, outdir


def true_main(mode):
    """The Main function, executes all operations except archival()"""
    if mode == 'test':
        source = sourcereader_test()
    else:
        source = sourcereader()
    twitter_csv = os.path.expanduser(r"~\Desktop\twitter.csv")
    twitter = open(twitter_csv, 'wb')
    twitter.close()
    entries = entry_mapper(source[0], full_gen(source[0]))
    flags = flag_mapper(source[0], nl_flags(source[0]))

    out = []

    out.extend(header(flags))
    out.extend(menu(flags, entries))
    out.extend(topstory(flags, entries))
    out.extend(publications(flags, entries))
    if len(entries['revs']) != 0:
        out.extend(reviews(flags, entries))
    if len(entries['scis']) != 0:
        out.extend(sciencenews(flags, entries))
    out.extend(industrynews(flags, entries))
    out.extend(policynews(flags, entries))
    out.extend(eventsnl(flags, entries))
    out.extend(jobsnl(flags, entries))
    out.extend(footer(flags))

    writetofile(out, source[1])
    wordpress(flags, entries, source[1])

    return out


def nl_flags(source):
    """Creates a default dictionary that returns a tuple containing a
    sentinal string and all indices where that string appears"""
    query = {'>>-->>Newsletter Name>>': 'nl',
             '>>-->>Newsletter Issue Number>>': 'issue',
             '>>-->>Newsletter Issue Date>>': 'date',
             # '>>-->>Subject Line>>':'subjectline',
             '>>-->>Homepage Banner Name>>': 'hpbanner',
             '>>-->>Old Jobs>>': 'oldjobs',
             ">>-->>Insert last week's jobs' HTML here>>": 'prevjobs',
             '>>-->>end of plaintext>>-->>': 'end'}

    line_count = 0
    # should probably convert to a regular dictionary
    sentinals = collections.defaultdict(list)
    for line in source:
        for cue in query:
            if cue in line:
                sentinals[query[cue]].append(line_count)
        line_count += 1

    return sentinals


def flag_mapper(source, sentinals):
    """Maps the nl_flags sentinals to the appropriate function and stores that
    information in a dictionary. When creating a new function dependent on a
    flag, call it from here"""

    func_map = {
        'nl': nl(source, sentinals['nl']),
        'issue': issue_number(source, sentinals['issue']),
        'date': issue_date(source, sentinals['date']),
        # 'subjectline':subjectline(source, sentinals['subjectline']),
        'hpbanner': homepagebanner(source, sentinals['hpbanner']),
        'oldjobs': job_grab(source, (sentinals['oldjobs'],
                                     sentinals['prevjobs'])),
        'prevjobs': job_grab(source, (sentinals['prevjobs'],
                                      sentinals['end'])),
        'end': end_init()}

    return func_map


def nl(source, index):
    """returns all the newsletter information"""
    newsletter = source[index[0] + 1].lower()
    return newsletter_info(newsletter)


def issue_number(source, index):
    """returns the Issue Number"""
    nl_issue = float(source[index[0] + 1])
    # need format for issues ending in 0
    return format(nl_issue, '.2f')


def issue_date(source, index):
    """Returns the issue date"""
    nl_date = str(source[index[0] + 1])
    return time.strptime(nl_date, '%B %d, %Y')


def subjectline(source, index):
    """Returns the subject line. This will be integrated into a csv writing
    function some time in the future"""
    return source[index[0] + 1]


def homepagebanner(source, index):
    """Returns the homepage banner in the proper format"""
    hpbanner = banner_gen(source, index)
    return hpbanner[0].homebanner_out()


def job_grab(source, indices):
    """This function is used to grab all the lines between the Old Jobs
    tag and the Previous Jobs tag, or all the lines between the Previous Jobs
    tag"""
    return [line for line in source[indices[0][0] + 1:indices[1][0] - 1]]


def end_init():
    """I put this here so that the end tag would have a function mapped to it
    This doesn't do anything for now."""
    print "All flags loaded"


def header(flag_map):
    """Creates the header"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    nl_date = flag_map['date']
    out = [
        '<html>',
        '<head>',
        '<title>Newsletter Issue</title>',
        ('<style type="text/css">a:link {text-decoration: none; color:' +
         newsletter['primary_color'] + ';}a:visited {text-decoration: none; color:' +
         newsletter['primary_color'] + ';}a:active {text-decoration: none; color:' +
         newsletter['primary_color'] +
         ';}a:hover {text-decoration: underline; color:' + newsletter['primary_color'] +
         ';}td {font-family: arial; font-size: 12px;}</style>'),
        '</head>',
        '<body>',
        ('<table class="webfix" style="border: 10px solid ' + newsletter['background_color'] +
         '; horizontal-align: center;" bgcolor="' + newsletter['background_color'] +
         '" align="center" width="755" border="0" cellpadding="0" '
         'cellspacing="0"><tr><td width="100%"><div align="center">'
         '<font color="#666666" size="1" face="Verdana">'),
        '',
        '<!-- #ISSUE Start -->',
        (newsletter['name_long'] + ' ' + nl_issue + ' ' +
         time.strftime("%B %d, %Y", nl_date).replace(' 0', ' ')),
        '<!-- #ISSUE End-->',
        '',
        '</font></div><img border="0" alt="' + newsletter['name_long'] +
        '" src="' + newsletter['header_image'] +
        ('" width="749" height="115"></td></tr><tr><td style="border-top: 1px '
         'solid ') + newsletter['primary_color'] + '; border-bottom: 1px solid ' +
        newsletter['primary_color'] + '; background-color: ' +
        newsletter['footer_background_color'] + '; vertical-align: middle;" bgcolor="' +
        newsletter['footer_background_color'] +
        ('" valign="middle" width="100%" height="30"><table border="0"'
         ' cellspacing="0" cellpadding="0" width="100%" height="30"><tr>'
         '<td valign="middle"><font size="2" face="arial" color="#666666">'),
    ]

    return out


def menu(flag_map, entry_map):
    """Creates the menu, will not produce science news or review links if
    you do not have any of those type of articles."""
    newsletter = flag_map['nl']
    out = ['', '<!-- #MENU Start -->']
    menu = ('<strong>&nbsp;&nbsp;&nbsp;&nbsp; In this issue:</strong> '
            '<a href="#currentpublications" style="text-decoration: none">'
            '<font color="' + newsletter['primary_color'] + '"><strong>Publications</strong>'
                                                            '</font></a> |')
    if len(entry_map['revs']) != 0:
        menu = (
            menu + ' <a href="#reviews" style="text-decoration: none">'
                   '<font color="' + newsletter['primary_color'] + '"><strong>Reviews</strong>'
                                                                   '</font></a> |')
    if len(entry_map['scis']) != 0:
        menu = (
            menu + ' <a href="#sciencenews" style="text-decoration: '
                   'none"><font color="' + newsletter['primary_color'] + '"><strong>Science '
                                                                         'News</strong></font></a> |')
    menu = (
        menu + ' <a href="#industrynews" style="text-decoration: none">'
               '<font color="' + newsletter['primary_color'] + '"><strong>Industry News</strong>'
               '</font></a> | <a href="#policynews" style="text-decoration:none"><font color="' +
        newsletter[
            'primary_color'] + '"><strong>Policy News'
                               '</strong></font></a> | <a href="#events" style='
                               '"text-decoration: none"><font color="' + newsletter['primary_color'] +
        '"><strong>Events</strong></font></a> | <a href='
        '"#jobopportunities" style="text-decoration: none"><font color'
        '="' + newsletter['primary_color'] + '"><strong>Jobs</strong></font></a>')

    out.extend(
        (menu,
         '<!-- #MENU End -->',
         '',
         (
             '</font></td><td><div align="center"><a href="http://www.facebook'
             '.com/CellTherapyNews"><img border=0 alt="Cell Therapy News on '
             'Facebook" src="http://img.en25.com/eloquaimages/clients/'
             'stemcelltechnologiesinc/%7B5d3d9c70-66c9-4e82-b056-abd80aef045e'
             '%7D_social_default_facebook_icon.jpg" width="16" height="16">'
             '</a>&nbsp;&nbsp;<a href="' + newsletter['twitter_url'] + '"><img border="0"'
                                                                       ' alt="' + str(newsletter['name_short']).upper()
             + ' on Twitter" src="http://img.en25.com/eloquaimages/clients/stemcelltechnologiesinc/'
               '%7B361a5c5c-663f-40fa-82b7-01c545266032%7D_social_default_'
               'twitter_icon.jpg" width="16" height="16"></a></div></td></tr>'
               '</table></td></tr><tr>'),
         ('<td style="padding-left: 50px; padding-right: 50px; background-'
          'color: #ffffff;" bgcolor="#ffffff">'),
         '',
         '<!-- #TOPSTORY Start -->',
         ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
          '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td '
          'style="padding-bottom: 15px;" width="100%" height="20"><font '
          'color="' + newsletter['primary_color'] + '" face="Arial" size="3"><strong>'
                                                    'TOP STORY</strong></font></td></tr><tr><td style="padding-'
                                                    'bottom: 15px;" width="100%">')))
    return out

def topstory(flag_map, entry_map):
    """Returns formatted Top Story as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    pubs = entry_map['pubs']
    banners = entry_map['banners']
    out = []
    out.extend(pubs[0][0].lineout_top(newsletter))
    out.extend(
        ('',
         '<!-- #TOPSTORY BANNER Start-->',
         banners[0].banner_out(newsletter, nl_issue, 1),
         '<!-- #TOPSTORY BANNER End-->'))
    out.extend(('</td></tr></table>', '<!-- #TOPSTORY End -->', ''))
    return out


def publications(flag_map, entry_map):
    """Returns formatted Publications as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    pubs = entry_map['pubs']
    banners = entry_map['banners']

    out = []
    out.extend(
        ('<!-- #PUBLICATIONS Start --><a name="currentpublications"></a>',
         ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
          '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style='
          '"padding-bottom: 15px;" width="100%" height="20"><strong>'
          '<font color="' + newsletter['primary_color'] +
          '" face="Arial" size="3">PUBLICATIONS</font></strong> <strong><font size="2" color="' +
          newsletter['primary_color'] + '">(<a style="text-decoration: none" href="'
                                        'http://thomsonreuters.com/products_services/science/free/essays/'
                                        'impact_factor/"><font color="' + newsletter['primary_color'] + '">Ranked by '
                                        'impact factor of the journal</font></a>)</font></strong></td>'
                                        '</tr><tr><td style="padding-bottom: 15px; border-bottom: 1px '
                                        'solid; border-bottom-color: #808080;">'),
         ''))

    if len(newsletter['division_list']) == 2 and newsletter['division_list'][0] != '':  # for named primaries
        out.extend(
            ('<font color="' +
             newsletter['primary_color'] +
             '" face="Arial" size="2"><strong>' +
             newsletter['division_list'][0] +
             '</strong></font><br><br>',
             ''))
    for pub in pubs[1]:
        out.extend(pub.lineout(newsletter))
        out.append('')

    # if a second division exists, fill second division
    if len(pubs[2]) > 0:
        out.extend(
            ('<font color="' +
             newsletter['primary_color'] +
             '" face="Arial" size="2"><strong>' +
             newsletter['division_list'][1] +
             '</strong></font><br><br>',
             ''))
        for pub in pubs[2]:
            out.extend(pub.lineout(newsletter))
            out.append('')

    # Subscribe text for Immunology newsletters
    if newsletter['name_short'] == 'hin' or newsletter['name_short'] == 'iidn' or newsletter['name_short'] == 'irn':
        if newsletter['name_short'] == 'hin':
            out.extend(
                [
                    ('<font size="2" color="#000000"><a target="_blank" style="'
                     'text-decoration: none" href="http://connexoncreative.com/'
                     'subscribe/?utm_source=newsletter&utm_medium=link&utm_camp'
                     'aign=hinnewslettersubscribe"><strong><font color="' +
                     newsletter['primary_color'] + '">Subscribe</font></strong></a> to our sister'
                                                   ' publications: <a target="_blank" style="text-decoration:'
                                                   ' none" href="http://www.immunologyofinfectiousdiseasenews'
                                                   '.com/"><strong><em><font color="' + newsletter['primary_color'] +
                     '">Immunology of Infectious Disease News</font></em>'
                     '</strong></a> and <a target="_blank" style="text-'
                     'decoration: none" href="http://www.immuneregulationnews.'
                     'com/"><em><strong><font color="' + newsletter['primary_color'] +
                     '">Immune Regulation News</font></strong></em></a></font>!'
                     '<br><br>'), ''])
        elif newsletter['name_short'] == 'iidn':
            out.extend(
                [
                    ('<font size="2" color="#000000">Don\'t forget to <a target'
                     '="_blank" style="text-decoration: none" href="http://connexon'
                     'creative.com/subscribe/?utm_source=newsletter&utm_medium='
                     'link&utm_campaign=iidnnewslettersubscribe"><strong><font '
                     'color="' + newsletter['primary_color'] + '">subscribe</font></strong></a> to '
                     'our sister publications: <a target="_blank" style="text-decoration: none" href="'
                     'http://www.humanimmunologynews.com/"><strong><em><font color="' +
                     newsletter[
                         'primary_color'] + '">Human Immunology'
                                            ' News</font></em></strong></a> and <a target="_blank" style="'
                                            'text-decoration: none" href="http://www.immuneregulationnews.'
                                            'com/"><em><strong><font color="' + newsletter[
                         'primary_color'] + '">Immune '
                                            'Regulation News</font></strong></em></a></font>!<br><br>'),
                    ''])
        else:
            out.extend(
                [
                    ('<font size="2" color="#000000"><a target="_blank" style="text'
                     '-decoration: none" href="http://connexoncreative.com/subscrib'
                     'e/?utm_source=newsletter&utm_medium=link&utm_campaign=irnnews'
                     'lettersubscribe"><strong><font color="' + newsletter['primary_color'] +
                     '">Subscribe</font></strong></a> to our sister publications:'
                     '<br> <a target="_blank" style="text-decoration: none" href="'
                     'http://www.humanimmunologynews.com/"><strong><em><font color="' +
                     newsletter['primary_color'] + '">Human Immunology News</font></em></strong></a>'
                                                   ' and <a target="_blank" style="text-decoration: none" href="'
                                                   'http://www.immunologyofinfectiousdiseasenews.com/"><em>'
                                                   '<strong><font color="' + newsletter[
                         'primary_color'] + '">Immunology of Infect'
                                            'ious Disease News</font></strong></em></a></font>!<br><br>'),
                    ''])

    # Adds the second banner
    out.extend(
        ('<!-- #PUBLICATIONS BANNER Start-->',
         banners[1].banner_out(newsletter, nl_issue, 2),
         '<!-- #PUBLICATIONS BANNER End-->'))

    # Adds footer
    out.extend(
        ('</td></tr></table>',
         '<!-- #PUBLICATIONS End -->',
         '',
         ''))
    for pub_set in pubs:
        for pub in pub_set:
            make_twitter_csv(pub, "pub")

    return out


def reviews(flag_map, entry_map):
    """Returns formatted Review Articles as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    revs = entry_map['revs']
    banners = entry_map['banners']

    out = [
        '<!-- #REVIEWS Start --><a name="reviews"></a>',
        ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color="' +
         newsletter['primary_color'] + '" face="Arial" size="3"><strong>REVIEWS</strong>'
                                       '</font></td></tr><tr><td style="padding-bottom: 15px; border-'
                                       'bottom: 1px solid; border-bottom-color: #808080;">'),
        '']

    for rev in revs:
        out.extend(rev.lineout(newsletter))
        out.append('')

    out.extend(
        ('<font color="#000000" face="Arial" size="2">Visit our <a style="text-'
         'decoration: none" href="' + newsletter['url'] + 'reviews/?utm_source='
                                                          'newsletter&utm_medium=link&utm_campaign=' + newsletter[
             'name_short'] +
         'newsletterreviews"><font color="' + newsletter['primary_color'] +
         '"><strong>reviews page</strong></font></a> to see a complete list of '
         'reviews in the ' + foi(newsletter) + ' research field.<br><br></font>', ''))

    if len(banners) > 2:
        # Note that I use '4' as the banner number to avoid appending iii
        # Instead of _mp
        out.extend(
            ('<!-- #REVIEWS BANNER Start-->',
             banners[2].banner_out(newsletter, nl_issue, 4),
             '<!-- #REVIEWS BANNER End-->'))
    else:
        out[-2] = re.sub('<br><br>', '', out[-2])

    out.extend(('</td></tr></table>', '<!-- #REVIEWS End -->', '', ''))

    space_in_csv(["Reviews"])

    for rev in revs:
        make_twitter_csv(rev, "rev")

    return out


def sciencenews(flag_map, entry_map):
    """Returns formatted Science News articles as a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    scis = entry_map['scis']
    textbanner = entry_map['textbanner']

    out = [
        '<!-- #SCIENCE Start --><a name="sciencenews"></a>',
        ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color="' +
         newsletter['primary_color'] + '" face="Arial" size="3"><strong>SCIENCE NEWS'
                                       '</strong></font></td></tr><tr><td style="padding-bottom: 15px; '
                                       'border-bottom: 1px solid; border-bottom-color: #808080;">'),
        '']

    for sci in scis:
        out.extend(sci.lineout(newsletter))
        out.append('')

    out.extend(('<!-- #SCIENCE BANNER Start-->',
                textbanner.text_massage(newsletter, nl_issue),
                '<!-- #SCIENCE BANNER End-->'))

    out.extend(('</td></tr></table>', '<!-- #SCIENCE End -->', '', ''))

    space_in_csv(["Science News"])

    for sci in scis:
        make_twitter_csv(sci, "sci")


    return out


def industrynews(flag_map, entry_map):
    """Returns formatted Industry News articles a list"""
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    scis = entry_map['scis']
    inds = entry_map['inds']
    textbanner = entry_map['textbanner']
    out = [
        '<!-- #INDUSTRY Start --><a name="industrynews"></a>',
        ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color="' +
         newsletter['primary_color'] + '" face="Arial" size="3"><strong>INDUSTRY NEWS'
                                       '</strong></font></td></tr><tr><td style="padding-bottom: 15px; '
                                       'border-bottom: 1px solid; border-bottom-color: #808080;">'),
        '']

    for ind in inds[:-1]:
        out.extend(ind.lineout(newsletter))
        out.append('')
    if len(scis) > 0:
        out.extend(inds[-1].lineout(newsletter, strip=True))
        out.append('')
    else:
        out.extend(inds[-1].lineout(newsletter))
        out.extend(('<!-- #INDUSTRY BANNER Start-->',
                    textbanner.text_massage(newsletter, nl_issue),
                    '<!-- #INDUSTRY BANNER End-->',
                    ''))

    out.extend(('</td></tr></table>', '<!-- #INDUSTRY End -->', '', ''))

    space_in_csv(["Industry News"])

    for ind in inds:
        make_twitter_csv(ind, "ind")

    return out


def policynews(flag_map, entry_map):
    """Returns formatted Policy News articles as a list"""
    newsletter = flag_map['nl']
    pols = entry_map['pols']
    out = [
        '<!-- #POLICY Start --><a name="policynews"></a>',
        ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color="' +
         newsletter['primary_color'] + '" face="Arial" size="3"><strong>POLICY NEWS</strong>'
                                       '</font></td></tr><tr><td style="padding-bottom: 15px; border-'
                                       'bottom: 1px solid; border-bottom-color: #808080;">'),
        '']

    if len(pols) > 0 and newsletter['name_short'] != 'esc':
        for pol in pols:
            out.extend(pol.lineout(newsletter))
            out.append('')

    if newsletter['name_short'] != 'esc':
        out.extend(
            ('<!-- #POLICY SECTION Start -->',
             ('<a style="text-decoration: none" href="http://grants.nih.gov'
              '/grants/guide/index.html"><strong><font color="') +
             newsletter['primary_color'] +
             '" size="2" face="Arial">',
             ('<!-- #POLICY TITLE-->National Institutes of Health '
              '(United States)<!-- End --></font></strong></a><br><br>'),
             '<!-- #POLICY SECTION End -->',
             ''))
        out.extend(
            ('<!-- #POLICY SECTION Start -->',
             ('<a style="text-decoration: none" href="'
              'http://www.fda.gov/Drugs/GuidanceComplianceRegulatory'
              'Information/Guidances/ucm121568.htm"><strong><font color="') +
             newsletter['primary_color'] +
             '" size="2" face="Arial">',
             ('<!-- #POLICY TITLE-->Food and Drug Administration '
              '(United States)<!-- End --></font></strong></a><br><br>'),
             '<!-- #POLICY SECTION End -->',
             ''))
        out.extend(
            ('<!-- #POLICY SECTION Start -->',
             ('<a style="text-decoration: none" href="http://www.fda.gov/'
              'BiologicsBloodVaccines/NewsEvents/default.htm">'
              '<strong><font color="') +
             newsletter['primary_color'] +
             '" size="2" face="Arial">',
             ('<!-- #POLICY TITLE-->Center for Biologics Evaluation and '
              'Research (United States)<!-- End --></font></strong></a>'
              '<br><br>'),
             '<!-- #POLICY SECTION End -->',
             ''))
        out.extend(
            ('<!-- #POLICY SECTION Start -->',
             ('<a style="text-decoration: none" href="http://bit.ly/'
              '1j4Ivvu"><strong><font color="') +
             newsletter['primary_color'] +
             '" size="2" face="Arial">',
             ('<!-- #POLICY TITLE-->European Medicines Agency '
              '(European Union)<!-- End --></font></strong></a><br><br>'),
             '<!-- #POLICY SECTION End -->',
             ''))
        out.extend(
            ('<!-- #POLICY SECTION Start -->',
             ('<a style="text-decoration: none" href="http://www.mhra.gov.uk'
              '/NewsCentre/index.htm"><strong><font color="') +
             newsletter['primary_color'] +
             '" size="2" face="Arial">',
             ('<!-- #POLICY TITLE-->Medicines and Healthcare Products '
              'Regulatory Agency (United Kingdom)<!-- End --></font>'
              '</strong></a><br><br>'),
             '<!-- #POLICY SECTION End -->',
             ''))
        out.extend(
            ('<!-- #POLICY SECTION Start -->',
             ('<a style="text-decoration: none" href="http://www.tga.gov.'
              'au/newsroom/news-latest.htm"><strong><font color="') +
             newsletter['primary_color'] +
             '" size="2" face="Arial">',
             ('<!-- #POLICY TITLE-->Therapeutic Goods Administration '
              '(Australia)<!-- End --></font></strong></a>'),
             '<!-- #POLICY SECTION End -->'))

    if newsletter['name_short'] == 'esc':
        for pol in pols[:-1]:
            out.extend(pol.lineout(newsletter))
            out.append('')
        out.extend(pols[-1].lineout(newsletter, strip=True))
        out.append('')

    out.extend(('</td></tr></table>', '<!-- #POLICY End -->', ''))

    if len(pols) != 0:
        space_in_csv(["Policy News"])

    for pol in pols:
        make_twitter_csv(pol, "pol")

    return out


def eventsnl(flag_map, entry_map):
    """Returns formatted events as a list"""
    newsletter = flag_map['nl']
    events = entry_map['events']

    out = [
        '<!-- #EVENT Start --><a name="events"></a>',
        ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;" width="100%" height="20"><font color="' +
         newsletter['primary_color'] + '" face="Arial" size="3"><strong>EVENTS</strong>'
                                       '</font></td></tr><tr><td style="padding-bottom: 15px; border-'
                                       'bottom: 1px solid; border-bottom-color: #808080;">'),
        '']

    for event in events:
        out.extend(event.nlout(newsletter))
        out.append('')

    out.extend(
        (('<font face="Arial" size="2">Visit our '
          '<a style="text-decoration: none" href="') +
         newsletter['url'] +
         'events/?utm_source=newsletter&utm_medium=link&utm_campaign=' +
         newsletter['name_short'] +
         'newsletterevents"><font color="' +
         newsletter['primary_color'] +
         ('"><strong>events page</strong></font></a> to see a complete '
          'list of events in the ') +
         foi(newsletter) +
         ' community.</font>',
         '</font></font></font></td></tr></table>',
         '<!-- #EVENT End -->',
         '',
         ''))

    return out


# Should has persistance
def jobsnl(flag_map, entry_map):
    """Returns formatted jobs as a list"""
    newsletter = flag_map['nl']
    prevjobs = flag_map['prevjobs']

    jobs = entry_map['jobs']
    out = ['<!-- #JOB Start --><a name="jobopportunities"></a>',
           ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
            '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
            'padding-bottom: 15px;" width="100%" height="20"><font color="' +
            newsletter['primary_color'] + '" face="Arial" size="3"><strong>JOB OPPORTUNITIES'
                                          '</strong></font></td></tr><tr><td style="padding-bottom: 15px; '
                                          'border-bottom: 1px solid; border-bottom-color: #808080;">'),
           '']

    for job in jobs:
        out.extend(job.nlout(newsletter))
        out.append('')

    out.extend(prevjobs)
    out.extend(
        ('',
         ('<br><font size="2" face="Arial" color="#000000"><a style="text-'
          'decoration: none" href="http://connexoncreative.com/job/?utm_source='
          'newsletter&utm_medium=link&utm_campaign=' + newsletter['name_short'] +
          'newslettersubmitjobs"><font color="' + newsletter['primary_color'] +
          '"><strong>Recruit Top Talent</strong></font></a>: Reach more than '
          '50,000 potential candidates by <a href="http://connexoncreative.com/'
          'job/?utm_source=newsletter&utm_medium=link&utm_campaign=' +
          newsletter['name_short'] + 'newslettersubmitjobs"><strong><font color="' +
          newsletter['primary_color'] + '"><u>posting</u></font></strong></a>'),
         (' your organization\'s career opportunities on the Connexon Creative '
          '<a href="http://connexoncreative.com/jobs/?utm_source=newsletter&utm'
          '_medium=link&utm_campaign=' + newsletter['name_short'] + 'newsletterjobs"><strong>'
                                                                    '<font color="' + newsletter[
              'primary_color'] + '"><u>Job Board</u></font></strong></a>'
                                 ' at no cost.'),
         '</font></td></tr></table>',
         '<!-- #JOB End -->',
         ''))

    return out


def footer(flag_map):
    newsletter = flag_map['nl']
    out = [
        '<!-- #FOOTER Start -->',
        ('<table width="100%" border="0" cellspacing="0" cellpadding="0">'
         '<tr><td width="100%" height="20">&nbsp;</td></tr><tr><td style="'
         'padding-bottom: 15px;"><br><div align="center"><font size="2" '
         'face="Arial" color="' + newsletter['primary_color'] + '"><strong>Have we missed an'
                                                                ' important article or publication in ' + newsletter[
             'name_long'] + '? <a style="'
                            'text-decoration: none" href="http://connexoncreative.com/publication'
                            '/"><font color="' + newsletter['primary_color'] + '">Click here to submit!</font></a>'
                            '<br><br><a style="text-decoration: none" href="http://www.'
                            'connexoncreative.com/give-feedback/"><font color="' +
         newsletter['primary_color'] +
         '">Comments or suggestions? Submit your feedback here</font></a>'
         '</strong></font>'),
        ('</div></td></tr></table></td></tr><tr><td style="border-top: 1px '
         'solid; border-top-color: ' + newsletter['footer_border_color'] + '; border-bottom: 1px '
                                                                           'solid; border-bottom-color: ' + newsletter[
             'footer_border_color'] + ';  background-color: ' +
         newsletter['footer_background_color'] + '; vertical-align: middle;" bgcolor="' +
         newsletter['footer_background_color'] + '" valign="middle" width="100%" height="30"><table '
                                                 'width="100%" height="30"><tr><td valign="middle"><font color='
                                                 '"#666666" size="2" face="Arial"><strong>Learn more about ' +
         newsletter['name_long'] + ':  </strong><a style="text-decoration: none" href="' +
         newsletter['url'] + 'issue/"><font color="' + newsletter['primary_color'] +
         '">Archives</font></a> | <a style="text-decoration: none" href="' +
         newsletter['url'] + 'events/">'),
        '<font color="' + newsletter['primary_color'] + '">Events</font></a>',
        (' | <a style="text-decoration: none" href=" http://connexoncreative.'
         'com/contact-us/">'),
        '<font color="' + newsletter['primary_color'] +
        '">Contact Us</font></a></font></td></tr></table></td></tr></table>',
        '<!-- #FOOTER End -->',
        '',
        '</body></html>']

    return out


def writetofile(out, outdir):
    outfile = codecs.open(outdir + r'\output.htm', 'w', 'utf-8-sig', 'replace')
    out = [line + u'\n' for line in out]
    outfile.writelines(out)
    outfile.close()


def wordpress(flag_map, entry_map, outdir):
    hpbanner = flag_map['hpbanner']
    newsletter = flag_map['nl']
    nl_issue = str(flag_map['issue'])
    nl_date = flag_map['date']
    revs = entry_map['revs']
    events = entry_map['events']
    jobs = entry_map['jobs']
    altfile = codecs.open(outdir + r'\wordpress.htm', 'w', 'utf-8-sig', 'replace')
    out = []
    out.extend((hpbanner, ''))
    [out.extend(rev.archive(newsletter, nl_issue, nl_date)) for rev in revs]
    [out.extend(event.archive()) for event in events]
    [out.extend(job.archive(newsletter)) for job in jobs]
    out = [line + u'\n' for line in out]
    altfile.writelines(out)

    print "Wordpress write successful"

    altfile.close()


def archival():
    """Archival Process. Prompts for the issue , but really uses the outfile"""
    root = Tkinter.Tk()
    root.withdraw()
    source = tkFileDialog.askopenfile(
        parent=root,
        initialdir=r"S:\CXN - Connexon\CXN Publications",
        title="Select Plaintext")
    outdir = os.path.dirname(source.name)

    html = codecs.open(outdir + r'\output.htm', 'r', 'utf-8-sig', 'replace')
    archive = codecs.open(
        outdir +
        '\\archive.htm',
        'w',
        'utf-8-sig',
        'replace')

    source.close()

    html = html.read()
    html = re.sub(
        (ur'[\?&]elq=~~eloqua\.\.type--emailfield\.\.syntax--recipientid~~&elq'
         ur'CampaignId=~~eloqua\.\.type--campaign\.\.campaignid--0\.\.'
         ur'fieldname--id~~'),
        u'',
        html)
    html = re.sub(
        ur'[\?&]elq=<span class=eloquaemail>recipientid</span>',
        u'',
        html)
    html = re.sub(ur'elqFormName=[a-z]+\d', u'elqFormName=cxn', html)
    html = re.sub(
        u'=<SPAN class=eloquaemail>EmailAddress</SPAN>',
        u'=<EMAIL>',
        html)
    html = re.sub(r"\(A\)", '(Archive)', html)
    html = re.sub(u'<a href="', u'<a target="_blank" href="', html)
    html = re.sub(
        u'<a style="text-decoration: none;" href="',
        u'<a target="_blank" style="text-decoration: none" href="',
        html,
        flags=re.IGNORECASE)
    html = re.sub(u'<a target="_blank" href="#', u'<a href="#', html)
    html = re.sub(
        u'<a target="_blank" style="text-decoration: none" href="#',
        u'<a style="text-decoration: none" href="#',
        html)
    html = re.sub(u'(?:<html>((?s).*)<body>)', u'<body>', html)
    html = re.sub(
        u'(?:<!-- #FOOTER End -->((?s).*)</html>)',
        u'<!-- #FOOTER End -->',
        html)

    archive.write(html)

    source.close()
    archive.close()


def make_twitter_csv(pub, section):
    """Builds a CSV out of the titles and Abstracts of each Publication and Review"""
    open_access = ''
    if "Full Article" in pub.anchor_list:
        open_access = "open"
    out = os.path.expanduser(r"~\Desktop\twitter.csv")
    with open(out, 'ab') as twitter_out:
        csv_out = csv.writer(twitter_out)
        csv_out.writerow([pub.title.encode('utf-8'), pub.link_list[0].encode('utf-8'), section, pub.source.encode('utf-8'), open_access])


def space_in_csv(title):
    out = os.path.expanduser(r"~\Desktop\twitter.csv")
    with open(out, 'ab') as twitter_out:
        csv_out = csv.writer(twitter_out)
        csv_out.writerow(title)


# In the future, this function could fill in basic info in the template
def give_template():
    """give_template() generates a new plaintext file in the directory the
    user selects."""
    root = Tkinter.Tk()
    root.withdraw()

    source = tkFileDialog.askdirectory(
        parent=root,
        initialdir=r"S:\CXN - Connexon\CXN Publications",
        title="Select Directory")
    shutil.copy('plaintext_template.txt', source)


if __name__ == "__main__":
    true_main('')
    PROMPT = raw_input('Would you like archive now? (Say "Y") ')
    if PROMPT.upper() == 'Y':
        archival()
    give_template()

    # Extra Line in New Jobs
    # TODO: Note when old job readded
    # TODO: Combine Top Story and Division Number into a "flag" category
    # TODO: URLLib to assess dead job links?
    # TODO: Red tags when first put in Eloqua. Why?
    # TODO: re.sub %26/& in banners, also banner source
    # TODO: Dir persistence between nl and arch
    # TODO: Auto openaccess tag for tweets
    # TODO: Concurrent Access to the CSV (Perhaps JSON instead)
    # TODO: Event banner generator?
    # TODO: Sort equal IF Publications by number of anchor links
    # TODO: Prompt error if event occurs before newsletter date
    # BUG: Banners did not appear in HN 5.42 Archival Version (Did not change
    # span class to <EMAIL>)
    # BUG: Washingon DC still has United States in archival version
    # TODO: Run true_main again prompt
    # BUG: cxn not replaced in textad of CSCN 3.43
    # TODO: Trailing Space Removal
    # BUG: Double <em> tag on Review article in CBN 6.43
    # TODO: Sort Science News by Conference Date?<file_sep>'''
Created on Aug 11, 2014

@author: memery
'''
from Bio import Entrez
Entrez.email = "<EMAIL>"
handle = Entrez.esearch("pubmed",term='"embryonic stem" or "induced pluripotent stem" and "last 5 days"[EPDAT]',sort='relevance')
record = Entrez.read(handle)
print record<file_sep>'''
Created on Aug 12, 2014

@author: memery
'''
import xlutils

print help(xlutils)