# Copyright (C) 2011, 2012, 2013, 2015, 2016, 2018 David Maxwell and Constantine Khroulev
#
# This file is part of PISM.
#
# PISM is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# PISM is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License
# along with PISM; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

"""Utility functions/objects that don't have a good home elsewhere."""

import PISM
import time
import sys

def convert(value, u1, u2):
    "Convert value from units u1 to u2."
    unit_system = PISM.Context().unit_system
    return PISM.convert(unit_system, value, u1, u2)

def prepare_output(filename, append_time=True):
    "Create an output file and prepare it for writing."
    ctx = PISM.Context()
    output = PISM.PIO(ctx.com, ctx.config.get_string("output.format"),
                      filename, PISM.PISM_READWRITE_MOVE)
    PISM.define_time(output,
                     ctx.config.get_string("time.dimension_name"),
                     ctx.config.get_string("time.calendar"),
                     ctx.time.units_string(),
                     ctx.unit_system)
    if append_time:
        PISM.append_time(output,
                         ctx.config.get_string("time.dimension_name"),
                         ctx.time.current())

    return output

def writeProvenance(outfile, message=None):
    """Saves the time and command line arguments (or the provided `message`) to
    the ``history`` attribute of the :file:`.nc` file `outfile`"""
    rank = PISM.Context().rank
    if rank == 0:
        nc = PISM.netCDF.Dataset(outfile, 'a')  # append
        if message is None:
            message = time.asctime() + ': ' + ' '.join(sys.argv)
        if 'history' in nc.ncattrs():
            nc.history = message + '\n' + nc.history
        else:
            nc.history = message
        nc.source = "PISM " + PISM.PISM_Revision
        nc.close()
    PISM.Context().com.barrier()


def fileHasVariable(filename, varname):
    """Returns ``True`` if the :file:`.nc` file `filename` contains an attribute named `varname`."""
    try:
        ds = PISM.netCDF.Dataset(filename)
        return varname in ds.variables
    finally:
        ds.close()

# The following was copied from matplotlib, which copied a python recipe.


class Bunch(dict):

    """
    Often we want to just collect a bunch of stuff together, naming each
    item of the bunch; a dictionary's OK for that, but a small do- nothing
    class is even handier, and prettier to use.  Whenever you want to
    group a few variables:

      >>> point = Bunch(datum=2, squared=4, coord=12)
      >>> point.datum
      By: Alex Martelli
      From: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52308"""

    def __init__(self,**kw):
        dict.__init__(self,kw)
        self.__dict__ = self
