
from __future__ import absolute_import

from tsgettoolbox.odo import convert
from tsgettoolbox.odo import odo
from tsgettoolbox.odo import resource

import pandas as pd

from tstoolbox import tsutils

# GHCND
# Global Historical Climatology Network - Daily

# pd.read_csv('ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/all/{0}.dly',
# skiprows=7,
# date_parser=testp,
# index_col=0,
# parse_dates=[[0,1]])


class ghcnd(object):
    def __init__(self, url, **query_params):
        params = {
            'station': None,
            'start_date': None,
            'end_date': None,
        }
        params.update(query_params)

        self.url = url
        self.query_params = params

# Function to make `resource` know about the new ghcnd type.


@resource.register(r'ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/all.*',
                   priority=17)
def resource_ghcnd(uri, **kwargs):
    return ghcnd(uri, **kwargs)

# Function to convert from ghcnd type to pd.DataFrame


@convert.register(pd.DataFrame, ghcnd)
def ghcnd_to_df(data, **kwargs):
    df = pd.read_fwf(data.url + '/' + data.query_params['station'] + '.dly',
                     widths=[11, 4, 2, 4] + [5, 1, 1, 1] * 31)
    newcols = ['station', 'year', 'month', 'code']
    for day in list(range(1, 32)):
        for col in ['', 'm', 'q', 's']:
            newcols.append('{0}{1:02}'.format(col, day))
    df.columns = newcols
    codes = ['TMAX',  # Temperature MAX (1/10 degree C)
             'TMIN',  # Temperature MIN (1/10 degree C)
             'PRCP',  # PReCiPitation (tenths of mm)
             'SNOW',  # SNOWfall (mm)
             'SNWD',  # SNoW Depth (mm)
             # Average cloudiness midnight to midnight from 30-second
             # ceilometer data (percent)
             'ACMC',
             # Average cloudiness midnight to midnight from manual observations
             # (percent)
             'ACMH',
             # Average cloudiness sunrise to sunset from 30-second ceilometer
             # data (percent)
             'ACSC',
             # Average cloudiness sunrise to sunset from manual observations
             # (percent)
             'ACSH',
             'AWDR',  # Average daily wind direction (degrees)
             'AWND',  # Average daily wind speed (tenths of meters per second)
             # Number of days included in the multiday evaporation total (MDEV)
             'DAEV',
             # Number of days included in the multiday precipiation total
             # (MDPR)
             'DAPR',
             # Number of days included in the multiday snowfall total (MDSF)
             'DASF',
             # Number of days included in the multiday minimum temperature
             # (MDTN)
             'DATN',
             # Number of days included in the multiday maximum temperature
             # (MDTX)
             'DATX',
             # Number of days included in the multiday wind movement (MDWM)
             'DAWM',
             # Number of days with non-zero precipitation included in multiday
             # precipitation total (MDPR)
             'DWPR',
             # Evaporation of water from evaporation pan (tenths of mm)
             'EVAP',
             # Time of fastest mile or fastest 1-minute wind (hours and
             # minutes, i.e., HHMM)
             'FMTM',
             'FRGB',  # Base of frozen ground layer (cm)
             'FRGT',  # Top of frozen ground layer (cm)
             'FRTH',  # Thickness of frozen ground layer (cm)
             'GAHT',  # Difference between river and gauge height (cm)
             # Multiday evaporation total (tenths of mm; use with DAEV)
             'MDEV',
             # Multiday precipitation total (tenths of mm; use with DAPR and
             # DWPR, if available)
             'MDPR',
             'MDSF',  # Multiday snowfall total
             # Multiday minimum temperature (tenths of degrees C; use with
             # DATN)
             'MDTN',
             # Multiday maximum temperature (tenths of degress C; use with
             # DATX)
             'MDTX',
             'MDWM',  # Multiday wind movement (km)
             # Daily minimum temperature of water in an evaporation pan (tenths
             # of degrees C)
             'MNPN',
             # Daily maximum temperature of water in an evaporation pan (tenths
             # of degrees C)
             'MXPN',
             'PGTM',  # Peak gust time (hours and minutes, i.e., HHMM)
             'PSUN',  # Daily percent of possible sunshine (percent)
             # Average temperature (tenths of degrees C) [Note that TAVG from
             # source 'S' corresponds to an average for the period ending at
             # 2400 UTC rather than local midnight]
             'TAVG',
             'THIC',  # Thickness of ice on water (tenths of mm)
             # Temperature at the time of observation (tenths of degrees C)
             'TOBS',
             'TSUN',  # Daily total sunshine (minutes)
             'WDF1',  # Direction of fastest 1-minute wind (degrees)
             'WDF2',  # Direction of fastest 2-minute wind (degrees)
             'WDF5',  # Direction of fastest 5-second wind (degrees)
             'WDFG',  # Direction of peak wind gust (degrees)
             'WDFI',  # Direction of highest instantaneous wind (degrees)
             'WDFM',  # Fastest mile wind direction (degrees)
             'WDMV',  # 24-hour wind movement (km)
             'WESD',  # Water equivalent of snow on the ground (tenths of mm)
             'WESF',  # Water equivalent of snowfall (tenths of mm)
             # Fastest 1-minute wind speed (tenths of meters per second)
             'WSF1',
             # Fastest 2-minute wind speed (tenths of meters per second)
             'WSF2',
             # Fastest 5-second wind speed (tenths of meters per second)
             'WSF5',
             'WSFG',  # Peak gust wind speed (tenths of meters per second)
             # Highest instantaneous wind speed (tenths of meters per second)
             'WSFI',
             'WSFM',  # Fastest mile wind speed (tenths of meters per second)
             ]

    # SN*# = Minimum soil temperature (tenths of degrees C)
    #        where * corresponds to a code
    #        for ground cover and # corresponds to a code for soil
    #        depth.
    #
    #        Ground cover codes include the following:
    #        0 = unknown
    #        1 = grass
    #        2 = fallow
    #        3 = bare ground
    #        4 = brome grass
    #        5 = sod
    #        6 = straw multch
    #        7 = grass muck
    #        8 = bare muck
    #
    #        Depth codes include the following:
    #        1 = 5 cm
    #        2 = 10 cm
    #        3 = 20 cm
    #        4 = 50 cm
    #        5 = 100 cm
    #        6 = 150 cm
    #        7 = 180 cm
    for i in range(9):
        for j in range(1, 8):
            codes.append('SN{0}{1}'.format(i, j))

    # SX*# = Maximum soil temperature (tenths of degrees C)
    #        where * corresponds to a code for ground cover
    #        and # corresponds to a code for soil depth.
    #        See SN*# for ground cover and depth codes.
    for i in range(9):
        for j in range(1, 8):
            codes.append('SX{0}{1}'.format(i, j))

    # WT** = Weather Type where ** has one of the following values:
    #
    #        01 = Fog, ice fog, or freezing fog (may include heavy fog)
    #        02 = Heavy fog or heaving freezing fog (not always distinquished
    #        from fog)
    #        03 = Thunder
    #        04 = Ice pellets, sleet, snow pellets, or small hail
    #        05 = Hail (may include small hail)
    #        06 = Glaze or rime
    #        07 = Dust, volcanic ash, blowing dust, blowing sand, or blowing
    #        obstruction
    #        08 = Smoke or haze
    #        09 = Blowing or drifting snow
    #        10 = Tornado, waterspout, or funnel cloud
    #        11 = High or damaging winds
    #        12 = Blowing spray
    #        13 = Mist
    #        14 = Drizzle
    #        15 = Freezing drizzle
    #        16 = Rain (may include freezing rain, drizzle, and freezing
    #        drizzle)
    #        17 = Freezing rain
    #        18 = Snow, snow pellets, snow grains, or ice crystals
    #        19 = Unknown source of precipitation
    #        21 = Ground fog
    #        22 = Ice fog or freezing fog
    codes.extend(['WT{0:02}'.format(i) for i in range(1, 23)])

    # WV** = Weather in the Vicinity where ** has one of the following values:
    #        01 = Fog, ice fog, or freezing fog (may include heavy fog)
    #        03 = Thunder
    #        07 = Ash, dust, sand, or other blowing obstruction
    #        18 = Snow or ice crystals
    #        20 = Rain or snow shower
    codes.extend(['WV{0:02}'.format(i) for i in [1, 3, 7, 18, 20]])

    for code in codes:
        tmpdf = df.ix[df['code'] == code, :]
        if len(tmpdf) == 0:
            continue
        tmpdf.set_index(['year', 'month'], inplace=True)
        tmpdf = tmpdf.ix[:, list(range(2, 126, 4))].stack()
        tmpdf.index = (tmpdf.index.get_level_values(0).astype(str).values
                       + '-'
                       + tmpdf.index.get_level_values(1).astype(str).values
                       + '-'
                       + tmpdf.index.get_level_values(2).astype(str).values)

        # Get rid of bad dates, for example April 31.
        tmpdf.index = pd.to_datetime(tmpdf.index, errors='coerce')
        tmpdf = tmpdf[pd.notnull(tmpdf.index)]

        tmpdf = pd.DataFrame(tmpdf)
        tmpdf.columns = [code]
        tmpdf = tmpdf.ix[tsutils.parsedate(data.query_params['start_date'],
                                           strftime='%Y-%m-%d'):
                         tsutils.parsedate(data.query_params['end_date'],
                                           strftime='%Y-%m-%d'), :]
        try:
            ndf = ndf.join(tmpdf)
        except NameError:
            ndf = tmpdf

    ndf.index.name = 'Datetime'
    ndf.replace(to_replace=[-9999], value=[None], inplace=True)
    return ndf


if __name__ == '__main__':
    r = resource(
        r'ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/all',
        station='ASN00075020',
        start_date='2000-01-01',
        end_date='2001-01-01',
    )

    as_df = odo(r, pd.DataFrame)
    print('ghcnd')
    print(as_df)

    r = resource(
        r'ftp://ftp.ncdc.noaa.gov/pub/data/ghcn/daily/all',
        station='ASN00075020',
        start_date='10 years ago',
        end_date='9 years ago',
    )

    as_df = odo(r, pd.DataFrame)
    print('ghcnd')
    print(as_df)
