# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.

from podaac.podaac import Podaac
from podaac.podaac_utils import PodaacUtils
import numpy as np
from ocw.dataset import Dataset
from netCDF4 import Dataset as netcdf_dataset
from netcdftime import utime
import os
import sys
import time
import itertools


def convert_times_to_datetime(time):
    '''Convert the time object's values to datetime objects

    The time values are stored as some unit since an epoch. These need to be
    converted into datetime objects for the OCW Dataset object.

    :param time: The time object's values to convert
    :type time: pydap.model.BaseType

    :returns: list of converted time values as datetime objects
    '''
    units = time.units
    # parse the time units string into a useful object.
    # NOTE: This assumes a 'standard' calendar. It's possible (likely?) that
    # users will want to customize this in the future.
    parsed_time = utime(units)
    return [parsed_time.num2date(x) for x in time[:]]


def list_available_level4_extract_granule_dataset_ids():
    '''Convenience function which returns an up-to-date \
        list of available level4 blended granule dataset id's which can be \
        used in the granule extraction service.
    :returns: a comma-seperated list of granule dataset id's.

    '''
    podaac_utils = PodaacUtils()
    return podaac_utils.list_level4_dataset_ids()


def subset_granule(variable, name='', path='/tmp', input_file_path=''):
    '''Subset Granule service allows users to Submit subset jobs. \
        Use of this service should be preceded by a Granule Search in \
        order to identify and generate a list of granules to be subsetted.

    :param variable: The name of the variable to read from the dataset.
    :type variable: :mod:`string`

    :param name: (Optional) A name for the loaded dataset.
    :type name: :mod:`string`

    :param path: (Optional) a path on the filesystem to store the granule.
    :type path: :mod:`string`

    :param input_file_path: path to a json file which contains the \
        the subset request that you want to send to PO.DAAC
    :type input_file_path: :mod:`string`

    :returns: a token on successful request reception. This can be \
        further used to check the status of the request.

    '''
    podaac = Podaac()
    if path is not None:
        path = os.path.dirname(os.path.abspath(__file__))
    granule_name = podaac.granule_subset(input_file_path, path)
    path = path + '/' + granule_name
    return read_dataset(name, granule_name, variable, path)

def extract_l4_granule(variable, dataset_id='', name='', path='/tmp'):
    '''Loads a Level4 gridded Dataset from PODAAC
    :param variable: The name of the variable to read from the dataset.
    :type variable: :mod:`string`

    :param dataset_id: dataset persistent ID. datasetId \
        is required for a granule search. Example: \
        PODAAC-CCF35-01AD5
    :type dataset_id: :mod:`string`

    :param name: (Optional) A name for the loaded dataset.
    :type name: :mod:`string`

    :param path: a path on the filesystem to store the granule.
    :type path: :mod:`string`

    :returns: A :class:`dataset.Dataset` containing the dataset pointed to by
        the OpenDAP URL.

    :raises: ServerError
    '''
    podaac = Podaac()
    if path is not None:
        path = os.path.dirname(os.path.abspath(__file__))
    granule_name = podaac.extract_l4_granule(
        dataset_id=dataset_id, path=path)
    print("Downloaded Level4 Granule '%s' to %s" % (granule_name, path))
    path = path + '/' + granule_name
    return read_dataset(name, granule_name, variable, path)

def read_dataset(name='', granule_name ='', variable=None, path='/tmp'):
    d = netcdf_dataset(path, mode='r')
    dataset = d.variables[variable]

    # By convention, but not by standard, if the dimensions exist, they will be in the order:
    # time (t), altitude (z), latitude (y), longitude (x)
    # but conventions aren't always followed and all dimensions aren't always present so
    # see if we can make some educated deductions before defaulting to just pulling the first three
    # columns.
    temp_dimensions = list(map(lambda x: x.lower(), dataset.dimensions))
    dataset_dimensions = dataset.dimensions
    time = dataset_dimensions[temp_dimensions.index(
        'time') if 'time' in temp_dimensions else 0]
    lat = dataset_dimensions[temp_dimensions.index(
        'lat') if 'lat' in temp_dimensions else 1]
    lon = dataset_dimensions[temp_dimensions.index(
        'lon') if 'lon' in temp_dimensions else 2]

    # Time is given to us in some units since an epoch. We need to convert
    # these values to datetime objects. Note that we use the main object's
    # time object and not the dataset specific reference to it. We need to
    # grab the 'units' from it and it fails on the dataset specific object.
    times = np.array(convert_times_to_datetime(d[time]))
    lats = np.array(d.variables[lat][:])
    lons = np.array(d.variables[lon][:])
    values = np.array(dataset[:])
    origin = {
        'source': 'NASA JPL PO.DAAC',
        'url': 'https://podaac.jpl.nasa.gov'
    }

    # Removing the downloaded temporary granule before creating the OCW
    # dataset.
    d.close()
    path = os.path.join(os.path.dirname(__file__), granule_name)
    os.remove(path)

    return Dataset(lats, lons, times, values, variable, name=name, origin=origin)
