#!/usr/bin/env python
# -*- coding: utf-8 -*-
# __BEGIN_LICENSE__
#  Copyright (c) 2009-2013, United States Government as represented by the
#  Administrator of the National Aeronautics and Space Administration. All
#  rights reserved.
#
#  The NGT platform is licensed 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.
# __END_LICENSE__


import os, glob, optparse, re, shutil, subprocess, sys, string, time

libexecpath = os.path.abspath(sys.path[0] + '/../libexec')
sys.path.insert(0, libexecpath) # prepend to Python path
from stereo_utils import get_asp_version

import asp_system_utils
asp_system_utils.verify_python_version_is_supported()

job_pool = [];

# Global output folder variable
outputFolder = ""

def man(option, opt, value, parser):
    print >>sys.stderr, parser.usage
    print >>sys.stderr, '''\
This program operates on LRO (.IMG) files, and performs the
following ISIS 3 operations:
 * Converts to ISIS format (lronac2isis)
 * Attaches SPICE information (spiceinit and spicefit)
 * Performs radiometric calibration (lronaccal)
 * lronacecho?
 * Removes camera distortions from the CCD images (noproj)
 * Performs jitter analysis (lrojitreg)
 * Mosaics individual CCDs into one unified image file (handmos)
 * Normalizes the mosaic (cubenorm)
'''

    sys.exit()

class Usage(Exception):
    def __init__(self, msg):
        self.msg = msg

def add_job( cmd, num_working_threads=4 ):
    if ( len(job_pool) >= num_working_threads):
        job_pool[0].wait();
        job_pool.pop(0);
    print(cmd)
    job_pool.append( subprocess.Popen(cmd, shell=True, env=os.environ) );

def wait_on_all_jobs():
    print("Waiting for jobs to finish")
    while len(job_pool) > 0:
        job_pool[0].wait();
        job_pool.pop(0);

# Go through a list of cubes and sort them into left/right pairs
def build_cube_pairs(cubePaths):
    pairDict = dict();

    for cube in cubePaths:
        print(cube)
        m = re.search('\D*(\d+)(.).*',os.path.basename(cube))
        number     = m.group(1)
        sideLetter = m.group(2)

        if (number not in pairDict):
            pairDict[number] = ['', ''];
        # Store the path in the spot for either the left or right cube
        if (sideLetter == "L"):
            pairDict[number][0] = cube; # Left
        else:
            pairDict[number][1] = cube; # Right
    return pairDict

def read_flatfile( flat ):
    # Fail if the input file is not present
    if not os.path.isfile(flat):
        raise Exception('File ' + flat + ' is missing!')

    averages = [0.0,0.0]

    f = open(flat,'r')
    for line in f:
        if ( line.rfind("Average Sample Offset:") >= 0 ):
            index       = line.rfind("Offset:");
            index_e     = line.rfind("StdDev:");
            crop        = line[index+7:index_e];
            if crop == " NULL ": # Check for null value
                raise Exception('Null sample offset in file ' + flat)
            averages[0] = float(crop);
        elif ( line.rfind("Average Line Offset:") >= 0 ):
            index       = line.rfind("Offset:");
            index_e     = line.rfind("StdDev:");
            crop        = line[index+7:index_e];
            if crop == "   NULL ": # Check for null value
                raise Exception('Null sample offset in file ' + flat)
            averages[1] = float(crop);
        elif ( line.rfind("Using IpFind result only:") >= 0 ):
            index       = line.rfind("only:");
            if (line[index + 7] == 1):
                print("Warning: This result based only on IpFind search.")
    print(str(averages))
    return averages

# Call lronac2isis on each input file, return list of output files.
def lronac2isis( img_files, threads, outputFolder ):
    lronac2isis_cubs = []
    for img in img_files:
        # Expect to end in .IMG, change to end in .cub and move to output folder
        newExtension = os.path.splitext(img)[0] + '.cub'
        cubFilePath  = os.path.join(outputFolder, os.path.basename(newExtension))
        if( os.path.exists(cubFilePath) ):
            print(cubFilePath + ' exists, skipping lronac2isis.')
        else:
            cmd = 'lronac2isis from='+ img +' to='+ cubFilePath
            add_job(cmd, threads)
        lronac2isis_cubs.append( cubFilePath )
    wait_on_all_jobs()
    return lronac2isis_cubs


# Call lronaccal on each input file, return list of output files.
def lronaccal( cub_files, threads, delete=False ):
    lronaccal_cubs = []
    for cub in cub_files:
        # Expect to end in .cub, change to end in .lronaccal.cub
        to_cub = os.path.splitext(cub)[0] + '.lronaccal.cub'
        if( os.path.exists(to_cub) ):
            print(to_cub + ' exists, skipping lronaccal.')
        else:
            cmd = 'lronaccal from='+ cub +' to='+ to_cub
            add_job(cmd, threads)
        lronaccal_cubs.append( to_cub )
    wait_on_all_jobs()

    if( delete ): # Delete all input .cub files and log files
        for cub in cub_files:
          os.remove( cub )
        lronaccal_log_files = glob.glob( os.path.commonprefix(cub_files) + '*.lronaccal.log' )
        for file in lronaccal_log_files:
          os.remove( file )
    return lronaccal_cubs


# Call lronacecho on each input file, return list of output files.
def lronacecho( cub_files, threads, delete=False ):
    lronacecho_cubs = []
    for cub in cub_files:
        # Expect to end in .cub, change to end in .lronaccal.cub
        to_cub =
 os.path.splitext(cub)[0] + '.lronacecho.cub'
        if( os.path.exists(to_cub) ):
            print(to_cub + ' exists, skipping lronacecho.')
        else:
            cmd = 'lronacecho from='+ cub +' to='+ to_cub
            add_job(cmd, threads)
        lronacecho_cubs.append( to_cu
b )
    wait_on_all_jobs()

    if( delete ): # Delete all input .cub files and log files
        for cub in cub_files:
          os.remove( cub )
    return lronacecho_cubs


def spice( cub_files, threads):
    for cub in cub_files:
        cmd = 'spiceinit web=false from='+ cub
        add_job(cmd, threads)
    wait_on_all_jobs()
    for cub in cub_files:
        cmd = 'spicefit from='+ cub
        add_job(cmd, threads)
    wait_on_all_jobs()
    return

# Returns true if the .cub LRONAC file has CROSSTRACK_SUMMING = 1
def isFileHalfRes(cubFilePath):

    return False; # It looks like the normal pvl file works so use it in all cases

    f = open(cubFilePath, 'r')
    for line in f:
        if ( line.rfind("CROSSTRACK_SUMMING") >= 0 ):
            index       = line.rfind("=");
            crop        = line[index+2];
            result      = (crop == "2")
    f.close()

    return result;


# Left file is/home/smcmich1 in index 0, right is in index 1
def noproj( file_pairs, threads, delete, fakePvl, outputFolder):
    if fakePvl: # Generate temporary PVL files containing LRONAC definition
                # - We need one for full-res mode, one for half-X-res mode.

       fullResFilePath = os.path.join(outputFolder, 'noprojInstruments_fullRes.pvl')
       if os.path.exists(fullResFilePath):
          print(fullResFilePath + ' exists, using existing file.')
       else: # Need to write the file
          print('Generating LRONAC compatible .pvl file ' + fullResFilePath)
          f = open(fullResFilePath, 'w')
          f.write('Object = IdealInstrumentsSpecifications\n');
          f.write('  UserName     = auto\n');
          f.write('  Created      = 2013-07-18T13:42:00\n');
          f.write('  LastModified = 2013-07-18T13:42:00\n\n');
          f.write('  Group = "LUNAR RECONNAISSANCE ORBITER/NACL"\n');
          f.write('     TransY = 16.8833\n')
          f.write('     ItransS = -2411.9\n')
          f.write('     TransX = 0.6475\n')
   