#!/usr/bin/env python

import time
import pandas as pd
import os.path
from optparse import OptionParser, OptionGroup
import requests

def main():
    opts, args = get_opts()
    # YOUR API KEY
    API_KEY = opts.apikey
    # Integer value of year YYYY
    year = int(opts.year)
    # Integer values of months to download
    months = [int(month.strip()) for month in opts.months.strip().split(',')]
    # URL for CAMD API hourly emissions files
    camd_url = opts.campd_url.strip()
    #########
    cems = CEMS()
    for month in months:
        mondf = pd.DataFrame()
        for day in date_range(month, year):
            print(day, flush=True)
            daystr = day.strftime('%Y-%m-%d')
            # Dates YYYY-MM-DD
            params = {'api_key': API_KEY, 'beginDate': daystr, 'endDate' : daystr, 
              'operatingHoursOnly': False}
            # Make up to 3 attempts
            for n in range(3): 
                req = requests.get(camd_url, params=params)
                if req.status_code == 200:
                    df = pd.DataFrame(req.json())
                    time.sleep(10)
                    break
                else:
                    print('\tTry: %s   Status: %s' %(n, req.status_code))
                    time.sleep(15)
            if req.status_code != 200:
                raise ValueError('Could not read emissions day')
            print('\tRecords: %s' %len(df), flush=True)
            mondf = pd.concat((mondf, df))
        mondf.rename(columns=cems.colmap, inplace=True)
        monname = day.strftime('%b').lower()
        fn = os.path.join(opts.output_path.strip(),
          '%s.txt' %'-'.join((opts.prefix.strip(), str(year), day.strftime('%b').lower(), 'hourly')))
        print('Writing %s records to %s' %(len(mondf), fn))
        mondf.to_csv(fn, index=False, columns=cems.cols)

def get_opts():
    '''
    Handle command line arguments and options.
    '''
    parser = OptionParser(usage = 'usage: %prog [options] get_camd_cems')
    parser.add_option('-a', '--apikey', dest='apikey', 
      help='Your data.gov API key', default='')
    parser.add_option('-y', '--year', dest='year', help='Year to process', default='2021')
    parser.add_option('-u', '--campd_url', dest='campd_url', 
      help='CAMPD Hourly Emissions URL', 
      default='https://api.epa.gov/easey/streaming-services/emissions/apportioned/hourly')
    parser.add_option('-o', '--output_path', dest='output_path', 
      help='Path to write monthly CEMs path', default='output')
    parser.add_option('-p', '--prefix', dest='prefix', 
      help='CAMDP CEMs emissions prefix', default='campd')
    parser.add_option('-m', '--months', dest='months', 
      help='Comma delimited list of months to download', default='1,2,3,4,5,6,7,8,9,10,11,12')
    return parser.parse_args()

def date_range(month, year):
    '''
    Get a list of datetimes for all days in a month
    '''
    d = pd.to_datetime(f'{month}{year}', format='%m%Y')
    return list(pd.date_range(start=d, periods=d.daysinmonth))

class CEMS:

    def __init__(self):
        # Column maps from the API to CEMs format
       self. colmap = {'stateCode': 'State', 'facilityName': 'Facility Name', 'facilityId': 'Facility ID',
          'unitId': 'Unit ID', 'associatedStacks': 'Associated Stacks', 'date': 'Date', 'hour': 'Hour',
          'opTime': 'Operating Time', 'grossLoad': 'Gross Load (MW)', 
          'steamLoad': 'Steam Load (1000 lb/hr)', 'heatInput': 'Heat Input (mmBtu)',
          'so2MassMeasureFlg': 'SO2 Mass Measure Indicator', 'so2Rate': 'SO2 Rate (lbs/mmBtu)',
          'so2Mass': 'SO2 Mass (lbs)', 'so2RateMeasureFlg': 'SO2 Rate Measure Indicator',
          'co2MassMeasureFlg': 'CO2 Mass Measure Indicator', 'co2Rate': 'CO2 Rate (short tons/mmBtu)',
          'co2Mass': 'CO2 Mass (short tons)', 'co2RateMeasureFlg': 'CO2 Rate Measure Indicator',
          'noxMassMeasureFlg': 'NOx Mass Measure Indicator', 'noxRate': 'NOx Rate (lbs/mmBtu)',
          'noxMass': 'NOx Mass (lbs)', 'noxRateMeasureFlg': 'NOx Rate Measure Indicator',
          'primaryFuelInfo': 'Primary Fuel Type', 'secondaryFuelInfo': 'Secondary Fuel Type',
          'unitType': 'Unit Type', 'so2ControlInfo': 'SO2 Controls', 'noxControlInfo': 'NOx Controls',
          'pmControlInfo': 'PM Controls', 'hgControlInfo': 'Hg Controls', 'programCodeInfo': 'Program Code',
          'heatInputMeasureFlg': 'Heat Input Measure Indicator'}
       self.cols = ['State','Facility Name','Facility ID','Unit ID','Associated Stacks','Date',
          'Hour','Operating Time','Gross Load (MW)','Steam Load (1000 lb/hr)','SO2 Mass (lbs)',
          'SO2 Mass Measure Indicator','SO2 Rate (lbs/mmBtu)','SO2 Rate Measure Indicator',
          'NOx Mass (lbs)','NOx Mass Measure Indicator','NOx Rate (lbs/mmBtu)',
          'NOx Rate Measure Indicator','CO2 Mass (short tons)','CO2 Mass Measure Indicator',
          'CO2 Rate (short tons/mmBtu)','CO2 Rate Measure Indicator','Heat Input (mmBtu)',
          'Primary Fuel Type','Secondary Fuel Type','Unit Type','SO2 Controls','PM Controls',
          'NOx Controls','Hg Controls','Program Code','Heat Input Measure Indicator']

if __name__ == '__main__':
    main()
