from __future__ import print_function
import argparse
import json
import os
import string
import sys

class Converter:
    ''''''
    def __init__(self, options):
        ''''''
        self.options = options
        self.input_json = None

    def load_json(self):
        '''Loads and parses input file
        '''
        if not self.options.input_filename:
            raise Exception('No input_filename specified in options')

        with open(self.options.input_filename) as fp:
            text = fp.read()
            self.input_json = json.loads(text)

        if not text:
            raise Exception('Input file missing, empty, or unreadable ({})' \
                .format(self.options.input_filename))
        print('Number of input posts: {}'.format(len(self.input_json)))

    def write_csv(self):
        if not self.options.output_filename:
            print('No output file specified')
            return

        # Base columns on those previously extracted from MongoDB
        # Main exception - drop tags and convert caption text to ascii letters, numbers & whitespace
        column_string = 'user.username,user.id,createdTime,caption.text,images.standard_resolution.url' + \
            ',location.latitude,location.longitude'
        column_names = column_string.split(',')

        with open(self.options.output_filename, 'w') as fp:
            fp.write(column_string)
            if self.options.state:
                fp.write(',state')
            if self.options.time_zone:
                fp.write(',timezone')
            fp.write('\n')

            for post in self.input_json:
                output_list = list()
                for column in column_names:
                    keys = column.split('.')
                    value = post
                    for key in keys:
                        value = value[key]

                    # Convert caption to lower case ascii letters, numbers, & whitespace
                    if column == 'caption.text':
                        value = self._to_ascii_string(value)

                    # Write lat/lon as double, everything else as string
                    if keys[-1] in ['latitude', 'longitude']:
                        output_list.append('{}'.format(value))
                    else:
                        output_list.append('"{}"'.format(value))

                # Append state
                if self.options.state:
                    output_list.append('"{}"'.format(self.options.state))

                # Append time zone
                if self.options.time_zone:
                    output_list.append('"{}"'.format(self.options.time_zone))

                output_string = ','.join(output_list)
                fp.write(output_string)
                fp.write('\n')

            print('Wrote {}'.format(self.options.output_filename))

    def _to_ascii_string(self, text):
        '''Also converts to lowercase and removes punctuation

        '''
        if not text:
            return None
        # Remove chars that are not ascii letters or whitespace
        filter_chars = set(string.ascii_letters + string.whitespace)
        filter_text = filter(lambda x: x in filter_chars, text)
        ascii_text = filter_text.encode('ascii', 'ignore')
        return ascii_text.lower()


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--input_filename', required=True, \
        help='Input file (json)')
    parser.add_argument('-o', '--output_filename', help='Output filename (csv)')
    parser.add_argument('-s', '--state', help='State name, included as last column')
    parser.add_argument('-z', '--time_zone', choices=['EST', 'CST', 'MST', 'PST'], \
        help='Time zone string')
    options = parser.parse_args()
    #print(options)

    converter= Converter(options)

    print('Loading input file {}'.format(options.input_filename))
    converter.load_json()

    converter.write_csv()
