import arcpy
from arcpy import env
from arcpy.sa import *
import os
import traceback
import sys
import tempfile

class NoRemnantsError (Exception):
    pass
class PageLayoutError(Exception):
    pass

class LicenseError(Exception):
    pass

class SpatialRefProjErrorMap (Exception):
    pass

class SpatialRefProjErrorRemFC (Exception):
    pass

class matchingSpRefsError (Exception):
    pass

class BoundaryProjError (Exception):
    pass


#needed for support of ArcGIS 10x
def getPolyfromExt(ext):
    d = arcpy.GetInstallInfo('desktop')
    ver = d['Version']
    if ver == "10.3":
        poly = ext.polygon
    else:
        pts = arcpy.Array()
        pts.add(ext.lowerLeft)
        pts.add(ext.upperLeft)
        pts.add(ext.upperRight)
        pts.add(ext.lowerRight)
        pts.add(ext.lowerLeft)
        poly = arcpy.Polygon(pts,ext.spatialReference)
        pts.removeAll()    
    return poly

   
def returnLinUnits(linUnits,outUnit):
    dist_units = linUnits.split()
    dist = dist_units[0]
    units = dist_units[1]
    if units == outUnit:
        return dist
    else:
        if outUnit == "Feet":
            if units == "Miles":
                cvFact = 5280
            elif units == "Meters":
                cvFact = 3.28084
            else:
                cvFact = 3280.84
            returnVal = float(dist) * cvFact
        else:
            if units == "Miles":
                cvFact = 1609.34
            elif units == "Feet":
                cvFact = 0.3048
            else:
                cvFact = 1000
            returnVal = float(dist) * cvFact
        return returnVal




try:
  #Check for spatial analyst license

  if arcpy.CheckExtension("Spatial") == "Available":
    arcpy.CheckOutExtension("Spatial")
  else:
    raise LicenseError
  #Get Variables
  remnants = arcpy.GetParameterAsText(0)
  study_area = arcpy.GetParameterAsText(1)
  cellsizeUnits = arcpy.GetParameterAsText(2)
  env.workspace = arcpy.GetParameterAsText(3)
  waterbodies = arcpy.GetParameterAsText(4)

  

  #Setting Enviornmental Variables
  env.overwriteOutput = 1
  #THIS IS IMPORTANT SINCE CONVERSIONS CAUSE DIFFICULTIES
  env.scratchWorkspace = env.workspace 

  remDesc = arcpy.Describe(remnants)
  arcpy.env.outputCoordinateSystem = remDesc.spatialReference

  if remDesc.DataType == "FeatureLayer":
    mxd = arcpy.mapping.MapDocument("CURRENT")
    if mxd.activeView == "PAGE_LAYOUT":
      raise PageLayoutError     
    df = arcpy.mapping.ListDataFrames(mxd, mxd.activeView)[0]
    if df.spatialReference.name != remDesc.spatialReference.name:
      raise SpatialRefProjErrorMap
    
  units = arcpy.env.outputCoordinateSystem.linearUnitName
  if "Foot" in units:
    outUnit = "Feet"
  elif "Meter" in units:
    outUnit = "Meters"
  else:
    arcpy.AddMessage("Projection has unknown units")
    raise SpatialRefProjErrorRemFC

  cellSize = returnLinUnits(cellsizeUnits,outUnit)
  env.cellSize = cellSize
  #env.extent = remnants   # Needs to be this due to analysis may go outside of boundary===============REALLY NEED TO DIAL THIS IN MORE++++++++++++++
  

     
  wsDesc = arcpy.Describe(arcpy.env.workspace)
  imgExt =""
  nameShpExt =""
  if wsDesc.workspaceType == "FileSystem":
    imgExt =".img"
    nameShpExt=".shp"


  if arcpy.Exists(remnants):
    arcpy.AddMessage("Creating Remnant Input......")
    if remDesc.DataType != "FeatureLayer":
      remnantsLayer = "remnants"
      arcpy.MakeFeatureLayer_management(remnants,remnantsLayer )
    else:
      remnantsLayer  = remnants


    projectBND = "xxlg_PrjBnd" + nameShpExt
    arcpy.CopyFeatures_management(study_area,projectBND)

     
    arcpy.SelectLayerByLocation_management(remnantsLayer,"intersect", projectBND)
    matchcount = int(arcpy.GetCount_management(remnantsLayer).getOutput(0))
    if matchcount == 0:
      raise NoRemnantsError


    remnantLayer = "xxlg_rem_feats" + nameShpExt
    #Need to make sure polygons touching are combined into one remnant   
    arcpy.Dissolve_management(remnantsLayer,remnantLayer,"#","#","SINGLE_PART","DISSOLVE_LINES")
    remDesc = arcpy.Describe(remnantLayer)
    remExtPoly = getPolyfromExt(remDesc.extent)
    bndDesc = arcpy.Describe(projectBND)
    bndExtPoly = getPolyfromExt(bndDesc.extent)
    combinePoly = remExtPoly.union(bndExtPoly)
    finalExt = combinePoly.extent
	 
    env.extent = finalExt
    fieldList = arcpy.ListFields(remnantLayer,"","OID")
    fieldName = fieldList[0].name
    arcpy.AddField_management(remnantLayer,"XXid","LONG")
    arcpy.CalculateField_management(remnantLayer,"XXid","!"+fieldName+"!","PYTHON_9.3") 
    
    remRaster = "xxlg_REMs"+imgExt #RegionGroup for MM's code
    arcpy.PolygonToRaster_conversion(remnantLayer,"XXid",remRaster,"MAXIMUM_COMBINED_AREA","",cellSize)
    env.snapRaster = remRaster
    whereClause = "Value >= 0"
    remEvalRaster = Con("xxlg_REMs"+imgExt,1,"#",whereClause)
    remEvalRaster.save("xxlg_REM_Ones"+imgExt) 
    #Creating waterbody grid
    waterInBnd = False
    if arcpy.Exists(waterbodies):
        watbodyDesc = arcpy.Describe(waterbodies)
        if watbodyDesc.DataType != "FeatureLayer":
          watbodyLayer = "watbodyLayer"
          arcpy.MakeFeatureLayer_management(waterbodies,watbodyLayer)
        else:
          watbodyLayer = waterbodies
        
        arcpy.SelectLayerByLocation_management(watbodyLayer,"intersect", projectBND)
        matchcount = int(arcpy.GetCount_management(watbodyLayer).getOutput(0))
        
        if matchcount != 0:
          waterInBnd = True
          fieldList = arcpy.ListFields(watbodyLayer,"","OID")
          fieldName = fieldList[0].name
          waterRaster = "xxlg_WaterBodies"+imgExt
          arcpy.PolygonToRaster_conversion(watbodyLayer,fieldName,waterRaster,"MAXIMUM_COMBINED_AREA","",cellSize)
          whereClause = "Value >= 0"
          waterMask = Con(waterRaster,1,"#",whereClause)
          waterMask.save("xxlg_WaterMask"+imgExt) 

      
    
    #Creating grid used in LF Tool
    notRem = IsNull("xxlg_REM_Ones"+imgExt)
    notRem.save("xxlg_NotRem"+imgExt)
    remLandFragGrid = Con("xxlg_NotRem"+imgExt,1,2,"Value = 1")
    remLandFragGrid.save("xxlg_remLFT"+imgExt)
    if waterInBnd:
      waterZero = Minus("xxlg_WaterMask"+imgExt,1)
      waterZero.save("xxlg_waterZero"+imgExt)
      remLFT_Final = CellStatistics(["xxlg_remLFT"+imgExt,"xxlg_waterZero"+imgExt],"MINIMUM","DATA")
    else:
      remLFT_Final = remLandFragGrid
    remLFT_Final.save("xxlg_remLFTin"+imgExt)
    #Conversion for GUIDOS
    arcpy.RasterToOtherFormat_conversion("xxlg_remLFTin"+imgExt,env.workspace,"TIFF")
    if arcpy.Exists("lg_guidosInput.tif"):
        arcpy.Delete_management("lg_guidosInput.tif")
        
    arcpy.Rename_management("xxlg_remLFTin.tif","lg_guidosInput.tif")
    arcpy.AddMessage("A new raster for input into GUIDOS has been made.  Use lg_guidosInput.tif found in "+env.workspace+".")
    
    
    arcpy.SelectLayerByAttribute_management(remnantsLayer,"CLEAR_SELECTION")
    arcpy.SelectLayerByAttribute_management(watbodyLayer,"CLEAR_SELECTION")
    arcpy.AddMessage("Cleaning intermediate files")
    dataList = arcpy.ListDatasets("xxlg_*")
    for d in dataList:
        try:
            #arcpy.AddMessage("Deleting "+d)
            arcpy.Delete_management(d)
            
        except:
            arcpy.AddWarning ("Could not delete "+d)
            continue    

    fcList = arcpy.ListFeatureClasses("xxlg_*")
    for fc in fcList:
        try:
            #arcpy.AddMessage("Deleting "+d)
            arcpy.Delete_management(fc)
            
        except:
            arcpy.AddWarning ("Could not delete "+fc)
            continue
    
except PageLayoutError:
    arcpy.AddError ("Application will not run in the Page Layout View. Please switch to Data View to run the analysis.")
    
except SpatialRefProjErrorMap:
    arcpy.AddError ("Current coordinate system used in the data frame does not match remnant layer coordinate system.  Applicaton requires both are set to the same coordinate system.")

except SpatialRefProjErrorRemFC:
    arcpy.AddError ("The remenants feature class must use a projected coordinate system to run")

except LicenseError:
    arcpy.AddError ("Spatial Analyst license is unavailable")   

except matchingSpRefsError:
    arcpy.AddError ("Spatial reference of data frame must match the spatial reference of the DEM being used") 

except NoRemnantsError:
    arcpy.AddError ("No remnant features are found within project area.  Analysis reguires remnants at minimum be present.")

except BoundaryProjError:
    arcpy.AddError ("Spatial reference of project boundary data must be the same as remnants layer.") 
    

except:
    #arcpy.AddMessage("exiting")
    tb = sys.exc_info()[2]
    tbinfo = traceback.format_tb(tb)[0]
    #arcpy.AddMessage("exiting2")
    pymsg = tbinfo + "\n" + str(sys.exc_type)+ ": " + str(sys.exc_value)

    arcpy.AddError(pymsg)
finally:
    arcpy.AddMessage("Guidos Prep Completed")
    #arcpy.CheckInExtension("Spatial")
   # arcpy.Delete_management("forGettingLoc")