import requests
import time
import pandas as pd
from datetime import date
from datetime import timedelta
import os.path
import csv
import zipfile
import json
import metadata_parsing_functions


def download_data(mode, version, n_max_tries, max_time_per_dl, start, stop, dl_root):

    base_url = 'http://data.ecan.govt.nz/data/{}/Air/Air%20quality%20data%20for%20a%20monitored%20site%20({})/CSV?SiteId={}&StartDate={}&EndDate={}&zip=1'
    #base_url = 'http://data.ecan.govt.nz/data/94/Air/Air quality data for a monitored site ({})/CSV?SiteId={}&StartDate={}&EndDate={}&zip=1'
    Headers = {'User-Agent': 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148'}
    # http://data.ecan.govt.nz/data/29/Air/Air%20quality%20data%20for%20a%20monitored%20site%20(10%20minute)/CSV?SiteId=3&StartDate=02%2F06%2F2024&EndDate=18%2F06%2F2024
    # http://data.ecan.govt.nz/data/98/Air/Air%20quality%20data%20for%20a%20monitored%20site%20(daily)/CSV?SiteId=&StartDate=&EndDate=&zip=1
    # http://data.ecan.govt.nz/data/94/Air/Air%20quality%20data%20for%20a%20monitored%20site%20(hourly)/CSV?SiteId=11&StartDate=03%2F06%2F2024&EndDate=18%2F06%2F2024&zip=1


    if mode == 'all':
        bdate = date(1990, 1, 1)
        edate = date.today() + timedelta(days=365)

        os.makedirs('{}/NZ_ECAN/original_files/{}/'.format(dl_root, version), exist_ok=True)

    elif mode == 'nrt':
        bdate = start # if code is run after 2 am, data from previous day will be available
        edate = stop + timedelta(days=365) # add 1 year so the recent year is included

        os.makedirs('{}/NZ_ECAN/original_files/nrt/'.format(dl_root), exist_ok=True)

    else:
        print('time mode inapplicable')

    # read metadata
    with open('{}/NZ_ECAN/metadata/{}/processed/NZ_ECAN_META.json'.format(dl_root, version), 'r', encoding='utf-8') as f:
        metadata = json.loads(f.read())

    if mode == 'nrt':
        version = mode # update version to nrt in order to store data in correct directory

    station_codes = list(metadata.keys())
    station_IDs = [i.split('_')[0] for i in station_codes] # cut out stations IDs
    station_IDs = list(set(station_IDs)) # remove duplicates

    # create date array, daily; format YYYYMMDD
    years = pd.date_range(bdate, edate, freq='Y') #.strftime('%Y%m%d').tolist()
    print(years.strftime('%Y').tolist())
    temporal_resolutions = {'hourly': 94, 'daily': 98, '10 minute': 29}

    # download
    for temporal_resolution in temporal_resolutions:
        for station_ID in station_IDs:

            os.makedirs('{}/NZ_ECAN/original_files/{}/NZ_ECAN_{}/'.format(dl_root, version, station_ID), exist_ok=True)
            download_location = '{}/NZ_ECAN/original_files/{}/NZ_ECAN_{}/'.format(dl_root, version, station_ID)

            for year in years:
                # yearly files
                start_date = date(year.year, 1, 1).strftime('%d/%m/%Y')
                end_date = date(year.year, 12, 31).strftime('%d/%m/%Y')
                file_name = temporal_resolution.replace(' ', '')+'_ID'+station_ID+'_'+year.strftime('%Y')

                n_tries = 0
                errcode = 999
                while (n_tries < n_max_tries) and (errcode != 200):
                    r = requests.get(base_url.format(temporal_resolutions[temporal_resolution], temporal_resolution, station_ID, start_date, end_date), timeout=max_time_per_dl, headers=Headers)
                    if r.status_code == 200:
                        with open(download_location+file_name+'.zip', 'wb') as file:
                            file.write(r.content)

                        # unzip
                        with zipfile.ZipFile(download_location+file_name+'.zip', 'r') as zip_file:
                            zip_file.extractall(download_location)
                        os.rename(download_location+'data.csv', download_location+file_name+'.csv')
                        os.remove(download_location+file_name+'.zip')

                        # open to see if it's empty
                        with open(download_location+file_name+'.csv', 'r', encoding='utf-8') as file:
                            data = pd.read_csv(file, header=None)
                        if data.iloc[0,0] == 'nodata':
                            os.remove(download_location+file_name+'.csv')
                            print('No data {} station {} start {} end {}'.format(temporal_resolution, station_ID, start_date, end_date))
                            errcode = r.status_code

                        print('Downloaded resolution {} station {} start {} end {}'.format(temporal_resolution, station_ID, start_date, end_date))
                        errcode = r.status_code

                    elif r.status_code == 404:
                        print('No resolution {} station {} start {} end {}'.format(temporal_resolution, station_ID, start_date, end_date))
                        errcode = 200 #skip
                    elif r.status_code == 500:  
                        print('Error 500 resolution {} station {} start {} end {}'.format(temporal_resolution, station_ID, start_date, end_date))
                        errcode = 200 #skip
                    
                    else:
                        # try again
                        print('Response error {}, attempt {}'.format(r.status_code, n_tries))
                        errcode = r.status_code
                        n_tries += 1
                        time.sleep(n_tries ** 2) # wait a lil more every time 

                if n_tries == n_max_tries:
                    print('Failed downloading resolution {} station {} start {} end {}, {} times in {} seconds, error code {}'.format(temporal_resolution, station_ID, start_date, end_date, n_tries, max_time_per_dl, errcode))
        

def download_metadata(n_max_tries, max_time_per_dl, version, dl_root, meta_basefile, meta_history, meta_params):

    url_metadata = 'http://data.ecan.govt.nz/data/180/Air/Air%20quality%20all%20stations%20and%20monitor%20channels/CSV'

    os.makedirs(dl_root+"/NZ_ECAN/metadata/"+version+"/network_provided/", exist_ok=True)
    os.makedirs(dl_root+"/NZ_ECAN/metadata/"+version+"/processed/", exist_ok=True)

    download_location = dl_root+"/NZ_ECAN/metadata/"+version+"/network_provided/NZ_ECAN_META_{}.csv"
    Headers = {'User-Agent': 'Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148'}

    r = requests.get(url_metadata, headers=Headers, timeout=max_time_per_dl)
    n_tries = 0
    errcode = 999
    today = date.today().strftime('%Y%m%d')

    while (n_tries < n_max_tries) and (errcode != 200):
        if r.status_code == 200:
            with open(download_location.format(today), 'wb') as outfile:
                outfile.write(r.content)

            print('Downloaded metadata')
            errcode = r.status_code

        elif r.status_code == 404:
            print("No metadata found, error 404")
            errcode = 200

        else:
            # try again
            print('Response error {}, attempt {}'.format(r.status_code, n_tries))
            errcode = r.status_code
            n_tries += 1
            time.sleep(n_tries ** 2) # wait a lil more every time 

    if n_tries == n_max_tries:
        print('Failed downloading {} {} times in {} seconds, error code {}'.format(url_metadata, n_tries, max_time_per_dl, errcode))
    time.sleep(1)

    # JSON ==========================================================================================================
    network = os.path.basename(__file__).split('_downloa')[0]
    present_meta_file_id = today

    metadata_parsing_functions.json_parser(dl_root, network, version, meta_basefile, meta_history, meta_params, present_meta_file_id)