# $Revision$ on $Date$
# The above revision line needs to be the first line for all techtk files
# Copyright (c) 2006 Ansys Inc
proc ::AIEnv::GUIManagement::TryLoadFromCache {} {
   global env

    if { [info exists env(AI_ENV_NOCACHE)]} { return 0}

	set CacheFile [FindValidCache]
	if { $CacheFile != "" } {
		source $CacheFile
		# Success
		return 1
	} else {
		# No cache file
		return 0
	}
}

proc ::AIEnv::GUIManagement::WriteCache {} {
	global errorInfo envCache globalCache
	global res_list
    
	#create the cache file name
	set CacheFile [CreateCacheFileName] 

    	set Cmd ""
        # Append resource file list
        if { [info exists res_list] } {
	    append Cmd "\#begin ResourceList\n"
	    append Cmd "set resource_list \"$res_list\"\n"
	    append Cmd "\#end ResourceList\n"
	}
        # Append environment list affect GUI
        if { [info exists envCache] } {
	    append Cmd "\#begin envCache\n"
	    foreach v [array names envCache] {
		append Cmd "set envCache($v) $envCache($v)\n"
	    }
	    append Cmd "\#end envCache\n"
	}

        if [info exists globalCache] {
	    append Cmd "\#begin globalCache\n"
	    foreach v $globalCache {
		append Cmd "set globalCache($v) [set ::$v]\n"
	    }
	    append Cmd "\#end globalCache\n"
	}

	set TreeNamespaces [namespace children ::struct::tree]

	foreach TreeNamespace $TreeNamespaces {
		# Get the data for this tree
		set ChildArrayName "${TreeNamespace}::children"
		set ParentArrayName "${TreeNamespace}::parent"
		set NextNodeCounter "${TreeNamespace}::nextUnusedNode"
		variable $ChildArrayName
		variable $ParentArrayName
		variable $NextNodeCounter

		set ChildArrayData [array get $ChildArrayName]
		set ParentArrayData [array get $ParentArrayName]
		set NextNodeVal [subst $[subst $NextNodeCounter]]
		# The namespaces are formed from the word tree and the
		# name of the Tree. So a tree named Foobar would have
		# the namespace treeFoobar.  Therefore, strip off
		# the first four characters to get the tree name from
		# the namespace
		set TreeName [string range [namespace tail $TreeNamespace] 4 end]

		append Cmd "\#------------- Data for tree: $TreeName ----------------------\n"
		append Cmd "namespace eval $TreeNamespace \{\n"
		# Write the data lists
		append Cmd "set ChildArrayData \{\n$ChildArrayData\n\}\n"
		append Cmd "set ParentArrayData \{\n$ParentArrayData\n\}\n"
		# Restore the arrays
		append Cmd "variable children\nvariable parent\nvariable noderoot\nvariable nextUnusedNode\n"
		append Cmd "array set children \$ChildArrayData\n"
		append Cmd "array set parent \$ParentArrayData\n"
		# Restore the node counter
		append Cmd "set nextUnusedNode $NextNodeVal\n"

		# Loop through all of the data storage for all of the nodes of this tree.
		set NodeDataArrays [info vars ${TreeNamespace}::node*]
		foreach NodeArray $NodeDataArrays {
			set NodeArrayName [namespace tail $NodeArray]
			set NodeArrayData [array get $NodeArray]
			append Cmd "variable $NodeArrayName\n"
			append Cmd "set NodeArrayData \{\n$NodeArrayData\n\}\n"
			append Cmd "array set $NodeArrayName \$NodeArrayData\n"
		}
		# Unset the temporary storage
		append Cmd "unset ChildArrayData\n"
		append Cmd "unset ParentArrayData\n"
		append Cmd "unset NodeArrayData\n"
		# Set the nextnode variable
		# Close off the namespace
		append Cmd "\}\n"
		# Set up the command routing
		append Cmd "interp alias \{\} ::$TreeName \{\} ::struct::tree::TreeProc $TreeName\n"
		append Cmd "\#---------------- End Data for Tree: $TreeName --------------------\n\n"
	}
	
	# Write out the data for the DEZs
	append Cmd "\#------------- DEZ Data ------------------\n"
	variable ::AIEnv::GUIManagement::DEZ::DEZData
	set DEZDataList [array get ::AIEnv::GUIManagement::DEZ::DEZData]
	append Cmd "namespace eval ::AIEnv::GUIManagement::DEZ \{\n"
	append Cmd "set DEZDataList \{\n$DEZDataList\n\}\n"
	append Cmd "array set DEZData \$DEZDataList\n"
	append Cmd "unset DEZDataList\n"
	append Cmd "\}\n"
	# Write out commands to restore the Object definitions
	append Cmd "\#------------- Restore Objects ----------------\n"
	variable ObjectList
	variable TypeArray
	foreach Object $ObjectList {
		append Cmd "RegisterObjectImpl $Object $TypeArray($Object)\n"
	}
	# Write out commands to restore the ItemName map
	variable ItemNameMap
	set ItemNameMapList [array get ItemNameMap]
	append Cmd "\#------------- ItemNameMap -------------------\n"
	append Cmd "namespace eval ::AIEnv::GUIManagement \{\n"
	append Cmd "set ItemNameMapList \{\n$ItemNameMapList\n\}\n"
	append Cmd "variable ItemNameMap\n"
	append Cmd "array set ItemNameMap \$ItemNameMapList\n"
	append Cmd "unset ItemNameMapList\n"
	append Cmd "\}\n"
	
	if [catch {
	    set FileID [open_with_encoding $CacheFile "w"]
	    puts $FileID $Cmd
	    close $FileID
	    
	    #WriteCacheIndex $CacheFile
	}] {
	    mess "Couldn't write cache file: $errorInfo\n"
	}
}

proc ::AIEnv::GUIManagement::IsCacheFileValid {CacheFile IncludeFileList EnvironmentVarList} {
    global env res_list

    # This is because most users won't be able to write the cache file
    if ![file writable $CacheFile] {
	return 1
    }
    
    set ValidCache 1

    set CacheFileTimeStamp [file mtime $CacheFile]
    foreach IncludeFile $IncludeFileList {
	if { $IncludeFile != "" } {
	    if { [file exists $IncludeFile] } {
		if { $CacheFileTimeStamp < [file mtime $IncludeFile] } {
		    return 0
		}
	    } else {
		return 0
	    }
	}
    }

    # Loop through all of the stored environment variables looking to see
    # if things have changed.  If the array EnvData contains an entry whose
    # value is set to -1, that signals that the particular environment
    # variable was referenced by an ifdef but not defined within the system
    # added global cache - Ganesan
    set fp [open_with_encoding $CacheFile r]
    if {$fp == ""} { return $ValidCache }

    gets $fp line
    if { [lsearch $line ResourceList] == 1 } {
	while {[gets $fp line] >= 0 } {
	    if {[lsearch $line ResourceList] == 1} {
		break
	    } else {
		eval $line
	    }
	}
    }
    if ![info exists resource_list] {
	return 0
    } else {
       if [info exists res_list] {
          if {[llength $res_list] != [llength $resource_list]} {
             return 0
          } else {
             foreach {n v} $res_list {
                set pos [lsearch $resource_list $n]
                if {$pos >= 0} {
                   set rev [lindex $resource_list [expr $pos + 1]]
                   if {$rev != $v} {
                      return 0
                   }
                } else {
                   return 0
                }
             }
          }
       } else {
           return $ValidCache
       }
    }
    
    gets $fp line
    if { [lsearch $line envCache] == 1 } {
	while {[gets $fp line] >= 0 } {
	    if {[lsearch $line envCache] == 1} {
		break
	    } else {
		eval $line
	    }
	}
    }

    gets $fp line
    if { [lsearch $line globalCache] == 1 } {
	while {[gets $fp line] >= 0 } {
	    if {[lsearch $line globalCache] == 1} {
		break
	    } else {
		eval $line
	    }
	}
    }
    close $fp

    if {(![info exists envCache]) && (![info exists globalCache])} {
	return $ValidCache
    }

    if [info exists envCache] {
	foreach v [array names envCache] {
	    if [info exists env($v)] {
		set curval 1
	    } else {
		set curval 0
	    }
	    if {$envCache($v) != $curval} {
		return 0
	    }
	}
    }

    if [info exists globalCache] {
	foreach v [array names globalCache] {
	    if [info exists ::$v] {
		set curval [set ::$v]
	    } else {
		return 0
	    }
	    if {$globalCache($v) != $curval} {
		return 0
	    }
	}
    }

    return $ValidCache
	
	if { [info exists EnvironmentVarList] } {
		array set EnvData $EnvironmentVarList
		set ArrayIter [array startsearch EnvData]
		while { [array anymore EnvData $ArrayIter] } {
			set EnvName [array nextelement EnvData $ArrayIter]
			set EnvValue $EnvData($EnvName)

			# Check to see, if an environment variable that was referenced during the
			# last build but not defined, is still not defined.
			if { $EnvValue == -1 } {
				if { [info exists env($EnvName)] == 1} {
					# The environment variable at least exists now, so invalidate
					# the cache
					set ValidCache 0
					break
				}
				# else #
					# The environment variable is still not defined, therefore the
					# cache is still valid
			} else {
				# The environment variable existed previously.
				# Check to see if the previously defined environment variable is 
				# now undefined.
				if { [info exists env($EnvName)] == 0} {
					set ValidCache 0
					break
				} else {
					# If we get here, the current environment variable existed previously,
					# and exists now. So check to see if the values have changed.
					if { $EnvValue != $env($EnvName) } {
						set ValidCache 0
						break
					}
					# else #
						# The environment variable existed previously, exists now, and
						# has the same value, therefore the cache is valid.
				}
			}
		}
	}
	return $ValidCache	
}

proc ::AIEnv::GUIManagement::AddIncludeFile {IncludeFileName} {
	variable IncludeFileList
	lappend IncludeFileList $IncludeFileName
}


proc ::AIEnv::GUIManagement::AddEnvironmentVariable {EnvName EnvValue} {
	variable EnvData
	set EnvData($EnvName) $EnvValue
}


proc ::AIEnv::GUIManagement::FindValidCache {} {
    variable CacheDir
    global AIEnvDir AIEnvProduct
    global res_list

    set resource_dir [file join  $AIEnvDir resource]
    set ResourceList [glob -nocomplain -dir $resource_dir *.ttkrf]
    set result_dir [file join  $AIEnvDir resource result-interfaces]
    set ResourceList [concat $ResourceList [glob -nocomplain -dir $result_dir *.ttkrf]]

    global v3_readers_dir
    if {[info exist v3_readers_dir] && [file isdirectory $v3_readers_dir]} {
       set ResourceList [concat $ResourceList \
              [glob -nocomplain -dir $v3_readers_dir *_format_aie.ttkrf]]
    }

    if [info exists AIEnvProduct] {
	set resource_dir [file join $resource_dir $AIEnvProduct]
	set ResourceList [concat $ResourceList [glob -nocomplain -dir $resource_dir *.ttkrf]]
    }
    set tech_dir [file join  $AIEnvDir techTK]    
    set ResourceList [concat $ResourceList  [glob -nocomplain -dir $tech_dir  *]]
    
    GetResourceList $ResourceList

    # No point to having multiple cache files.
    set file [file join $CacheDir ai_env.cache]
    if ![file readable $file] {
	return ""
    }
    
    set EnvDataList ""
    if { [IsCacheFileValid $file $ResourceList $EnvDataList] == 1 } {
	return $file
    } else {
	return ""
    }
    
	variable PersistentCacheArray
	set IndexFile [GetCacheIndexFileName]
	if {[file exists $IndexFile] == 1} {
		source $IndexFile
	} else {
		# Delete any old cache files
		set NextCacheFileIndex [FindSafeCacheFileIndex]
		return ""
	}
	
	if {[info exists PersistentCacheArray] == 1} {
		set CacheFiles $PersistentCacheArray(CacheFiles)
		
		foreach File $CacheFiles {
			set EnvDataList $PersistentCacheArray($File,EnvList)
			set ResourceList $PersistentCacheArray($File,ResourceList)
			if { [IsCacheFileValid $File $ResourceList $EnvDataList] == 1 } {
				return $File
			}
		}
	} else {
		return ""
	}
	return ""
}


proc ::AIEnv::GUIManagement::unused__WriteCacheIndex {CurrentCacheFile} {
	variable PersistentCacheArray
	variable EnvData
	variable IncludeFileList
	variable NextCacheFileIndex
	set IndexFile [GetCacheIndexFileName]
	if {[file exists $IndexFile] == 1} {
		source $IndexFile
	} 
	PruneCacheIndex
	lappend PersistentCacheArray(CacheFiles) $CurrentCacheFile
	set PersistentCacheArray($CurrentCacheFile,EnvList) [array get EnvData]
	set PersistentCacheArray($CurrentCacheFile,ResourceList) $IncludeFileList
		
	# Write out the data
	set NextCacheFileIndex [FindSafeCacheFileIndex]
	set PersistentCacheArrayList [array get PersistentCacheArray]
	append Cmd "namespace eval ::AIEnv::GUIManagement \{\n"
	append Cmd "variable PersistentCacheArray\n"
	append Cmd "variable NextCacheFileIndex\n"
	append Cmd "set PersistentCacheArrayList \{\n$PersistentCacheArrayList\n\}\n"
	append Cmd "array set PersistentCacheArray \$PersistentCacheArrayList\n"
	append Cmd "set NextCacheFileIndex $NextCacheFileIndex\n"
	append Cmd "unset PersistentCacheArrayList\n"
	append Cmd "\}\n"
	
	set FileID [open_with_encoding $IndexFile "w"]
	puts $FileID $Cmd
	close $FileID
		
}

proc ::AIEnv::GUIManagement::unused__PruneCacheIndex {} {
	variable PersistentCacheArray
	
	if { [info exists PersistentCacheArray] == 1 } {
		set CacheFiles $PersistentCacheArray(CacheFiles)
		foreach File $CacheFiles {
			# Check to see if the cache files have been deleted.
			# If so, prune the index
			if { [file exists $File] == 0 } {
				# Remove the cache file from the index
				unset PersistentCacheArray($File,EnvList)
				unset PersistentCacheArray($File,ResourceList)
			} else {
				lappend NewCacheFileList $File
			}
		}
		if { [info exists NewCacheFileList] == 1 } {
			set PersistentCacheArray(CacheFiles) $NewCacheFileList
		} else {
			set PersistentCacheArray(CacheFiles) ""
		}
	}
}

proc ::AIEnv::GUIManagement::CreateCacheFileName {} {
	variable CacheDir
	variable NextCacheFileIndex
    
        # No point to having multiple cache files.
    return [file join $CacheDir ai_env.cache]
	
	if { [info exists NextCacheFileIndex] == 0 } {
		# Look to see if we have an index file, and if so,
		# source that file
		set IndexFile [GetCacheIndexFileName]
		if { [file exists $IndexFile] } {
			source $IndexFile
		} else {
			set NextCacheFileIndex [FindSafeCacheFileIndex]
			# Construct a cache file name
		}
	}
	set CacheFileName [file join $CacheDir icemfea_${NextCacheFileIndex}.cache]
	return $CacheFileName
}

proc ::AIEnv::GUIManagement::GetResourceList {IncludeFileList} {
    global env res_list

 #tk_messageBox -message "Building resource list" -type ok
    set res_path ""
    if {[info exists env(MED_ROOT)]} {
       set res_path [string toupper $env(MED_ROOT)]
    } elseif {[info exists env(ICEM_ACN)]} {
       set res_path [string toupper $env(ICEM_ACN)]
    }
    set res_list {}
    foreach IncludeFile $IncludeFileList {
	if { $IncludeFile != "" } {
             set ext [file extension $IncludeFile]
	    if { [file exists $IncludeFile] && [file isfile $IncludeFile] && ($ext == ".tcl" || $ext == ".ttkrf")} {
                 set file1 ""
                 set res_file ""
                 set oldfile $IncludeFile
                 set file1 [file dirname $IncludeFile]
                 while { $file1 != "" && [string toupper $file1] != $res_path} {
                    set res_file [file join  [file tail $oldfile] $res_file]
                    set oldfile $file1
                    set file1 [file dirname $file1]
                 }
                 set res_file [file join  [file tail $oldfile] $res_file]
                 lappend res_list $res_file
	       set fp [open $IncludeFile r]
	       if {$fp == ""} continue   
	       gets $fp line
                 set var ""
                 set tmp [regexp {Revision: ([^ ]+)} $line "" var]
                 if {$var == ""} {set var -1}
                 lappend res_list $var
                 close $fp
	    }
	}
    }	

}

proc ::AIEnv::GUIManagement::unused__GetCacheIndexFileName {} {
	variable CacheDir
	return [file join $CacheDir index.dat]
}

proc ::AIEnv::GUIManagement::unused__FindSafeCacheFileIndex {} {
	# Look through to see if we have any cache files
	# and try and determine the next available number
	variable CacheDir
	set CurDir [pwd]
	cd $CacheDir
	set CacheFiles [glob -nocomplain *.cache]
	cd $CurDir
	set HighestFileID 0
	foreach File $CacheFiles {
		set FileNumber [lindex [split [file rootname $File] "_"] 1]
		if { $FileNumber >= $HighestFileID } {
			set HighestFileID $FileNumber
			incr HighestFileID
		}
	}
	return $HighestFileID
}





