#!/usr/bin/env python

"""
Observation

Inherits from: LSSTObject : object

Class Description
The Observation class describes the result of the act of observing a
patch of the sky at a given time, under given weather and sky
conditions. Observation instances can be thought as small databases
recordding the state of the sky, weather, telescope etc. at the
time the exposure was taken.

Observation instances are generated by instances of the Proposal class
when each Proposal object is activated. Observation objects are then
given a ranking (which is updated after each exposure is taken) and
are inserted in the MasterScheduler queue. Eventually they are
executed.


Method Types
Constructor/Initializers
- __init__

Handle Priorities
- closeObservation

Weather Queries (is it necessary?)
- updateSeeing

Accessors
- [get|set]Rank
- getExpTime
- getProposal
- getPointing
- getRA
- getDec
- getMaxSeeing
- setDate
"""

from utilities import *
from LSSTObject import *

class Observation(LSSTObject):
    def __init__(self, dateProfile, moonProfile, propRank=0, proposal=None, propID=None, subsequence=None,
                 pairNum=0, ra=0.0, dec=0.0, filter=None, maxSeeing=None, exposureTime=0, fieldID=None,
                 seqn=0, rawSeeing=None, seeing=None, transparency=None, cloudSeeing=None, slewTime=None,
                 slewDistance=None, fieldFilterInterval=None, fieldInterval=None, fieldVisits=None,
                 airmass=None, skyBrightness=None, altitude=None, azimuth=None, distance2moon=None,
                 moonPhase=None, exclusiveBlockRequired=False, log=False, logfile=None, verbose=0):
        """
        Standard initializer.

        propRank:       initial rank/ranking.
        proposal:   the Proposal object this Observation is part of.
        ra:         RA (in decimal degrees).
        dec:        Dec (in decimal degrees).
        filter:     name/identifier of the filter to use.
        maxSeeing:  maximum value of acceptable seeing.
        exposureTime:    time to expose (in seconds).
        fieldID:    field ID corresponding to ra and dec. Redundant
                    but useful to save time.
        seqn:       sequence number within NEA-style repetition group
        date:       the date at which to observe (in seconds from the
                    beginning of the current year).
        seeing:     the current seeing value.
        slewTime:   the actual time it took to move there.
        airmass:    the current value of airmass.
        skyBrightness: the current value of the sky brightness.
        log:        False if not set; else log = logging.getLogger("....")
        logfile:    name (and path) of the desired log file (defaults to None)
        verbose:    Log verbosity:-1=none, 0=minimal, 1=wordy, >1=verbose
        """
        self.obsType = 0
        self.proposal = proposal
        if self.proposal:
            self.propID = self.proposal.propID
        else:
            self.propID = propID
        self.subsequence = subsequence
        self.fieldID = fieldID
        self.filter = filter
        self.seqn = seqn
        self.pairNum = pairNum
        (self.date, self.mjd, self.lst) = dateProfile
        self.night = -1
        self.exposureTime = exposureTime
        self.visitTime = 30.0
        self.slewTime = slewTime
        self.slewDistance = slewDistance
        self.fieldFilterInterval = fieldFilterInterval
        self.fieldInterval = fieldInterval
        self.fieldVisits = fieldVisits
        self.propRank = propRank
        self.finRank = 0.0
        self.maxSeeing = maxSeeing
        self.rawSeeing = rawSeeing
        self.seeing = seeing
        self.transparency = 0.0
        self.cloudSeeing = 0.0
        self.airmass = airmass
        self.skyBrightness = skyBrightness
        self.filterSkyBright = 0.0
        self.ra = ra
        self.dec = dec
        self.altitude = altitude
        self.azimuth = azimuth
        self.parallactic = 0.0
        self.distance2moon = 0.0
        self.rotatorSkyPos = 0.0
        self.rotatorTelPos = 0.0
        self.sunAlt = 0.0
        self.sunAz = 0.0
        self.phaseAngle = 0.0
        self.extinction = 0.0
        self.rScatter = 0.0
        self.mieScatter = 0.0
        self.moonAlt = 0.0
        self.moonAz = 0.0
        self.moonIllum = 0.0
        self.moonBright = 0.0
        self.darkBright = 0.0
        self.solarElong = 0.0        # degrees not radians
        self.exclusiveBlockRequired = exclusiveBlockRequired

        (self.moonRA_RAD, self.moonDec_RAD, self.moonPhase) = moonProfile

        self.log = log
        self.logfile = logfile
        self.verbose = verbose

        return

    def updateSeeing(self):
        """
        Query self.proposal to fetch the current seeing value and
        update self.seeing (is it really necessary?).
        """
        seeing = self.proposal.getSeeing()
        self.seeing = seeing
        return

    # Accessor Methods
    def getRank(self):
        """
        Return the current Observation rank.
        """
        return self.propRank

    def setPropRank(self, p):
        """
        Set the Observation rank to p.
        """
        self.propRank = float(p)
        return

    def setSeqn(self, p):
        """
        Set the Observation sequence to p.
        """
        self.seqn = int(p)
        return

    def getExpTime(self):
        """
        Return the Observation exposure time (in seconds).
        """
        return self.exposureTime

    def getProposal(self):
        """
        Return the Observation Proposal instance.
        """
        return (self.proposal)

    def getPointing(self):
        """
        Return the 2 element array [ra, dec]. Both ra and dec are in
        decimal degrees
        """
        return (self.ra, self.dec)

    def getRA(self):
        """
        Return RA in decimal degrees
        """
        return self.ra

    def getDec(self):
        """
        Return Dec in decimal degrees
        """
        return self.dec

    def getMaxSeeing(self):
        """
        Return the maximum acceptable seeing.
        """
        return self.maxSeeing

    def setDate(self, date):
        """
        Set the Observation date to date (in seconds from the
        beginning of the year).
        """
        self.date = date
        return

    def loadTargetData(self, ra, dec, fieldID, filter, exposureTime, slewTime, date):
        """
        Load minimalist Obs necessary for slew calculation
        """
        self.ra = ra
        self.dec = dec
        self.fieldID = fieldID
        self.filter = filter
        self.exposureTime = exposureTime
        self.slewTime = slewTime
        self.date = date
        return
