package org.sugarj.common;


import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;

import org.spoofax.interpreter.terms.IStrategoTerm;
import org.sugarj.common.path.AbsolutePath;
import org.sugarj.common.path.Path;
import org.sugarj.common.path.RelativePath;
import org.sugarj.util.Renaming;


/**
 * Shared execution environment.
 * 
 * @author Sebastian Erdweg <seba at informatik uni-marburg de>
 */
public class Environment implements Serializable {
  
  private static final long serialVersionUID = -8403625415393122607L;

  public static Map<Path, IStrategoTerm> terms = new WeakHashMap<Path, IStrategoTerm>();
  
  public static String sep = "/";
  public static String classpathsep = File.pathSeparator;
  
  private boolean generateFiles;
  
  private Path cacheDir = null;

  private Path root = new AbsolutePath(".");
  
  private Path bin = new AbsolutePath(".");

  /**
   * The directory in which to place files at parse time.
   */
  private final Path parseBin;
  
  /* 
   * parse all imports simultaneously, i.e., not one after the other
   */
  private boolean atomicImportParsing = false;
  
  /*
   * don't check resulting sdf and stratego files after splitting
   */
  private boolean noChecking = false;

  private Path tmpDir = new AbsolutePath(System.getProperty("java.io.tmpdir"));
  
  private Set<Path> sourcePath = new HashSet<Path>();
  private Set<Path> includePath = new HashSet<Path>();
  
  /**
   * List of renamings that need to be applied during compilation.
   */
  private List<Renaming> renamings = new LinkedList<Renaming>();
  
  public Environment(boolean generateFiles, Path stdlibDirPath) {
    this.includePath.add(bin);
    this.includePath.add(stdlibDirPath);
    this.generateFiles = generateFiles;
    try {
      this.parseBin = FileCommands.newTempDir();
      this.includePath.add(parseBin);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
  
  public Path getRoot() {
    return root;
  }

  public void setRoot(Path root) {
    this.root = root;
  }

  public Set<Path> getSourcePath() {
    return sourcePath;
  }

  public void setSourcePath(Set<Path> sourcePath) {
    this.sourcePath = sourcePath;
  }

  public Path getBin() {
    return bin;
  }

  public void setBin(Path bin) {
    if (this.bin!=null)
      includePath.remove(this.bin);
    this.bin = bin;
    includePath.add(bin);
  }

  public Path getCacheDir() {
    return cacheDir;
  }

  public void setCacheDir(Path cacheDir) {
    this.cacheDir = cacheDir;
  }

  public Path getParseBin() {
    return parseBin;
  }

  public boolean isAtomicImportParsing() {
    return atomicImportParsing;
  }

  public void setAtomicImportParsing(boolean atomicImportParsing) {
    this.atomicImportParsing = atomicImportParsing;
  }

  public boolean isNoChecking() {
    return noChecking;
  }

  public void setNoChecking(boolean noChecking) {
    this.noChecking = noChecking;
  }

  public Path getTmpDir() {
    return tmpDir;
  }

  public void setTmpDir(Path tmpDir) {
    this.tmpDir = tmpDir;
  }

  public Set<Path> getIncludePath() {
    return includePath;
  }

  public void setIncludePath(Set<Path> includePath) {
    this.includePath = includePath;
  }

  private RelativePath createCompileBinPath(String relativePath) {
    return new RelativePath(bin, relativePath);
  }
  
  public RelativePath createCachePath(String relativePath) {
    return new RelativePath(cacheDir, relativePath);
  }
  
  private RelativePath createParseBinPath(String relativePath) {
    return new RelativePath(parseBin, relativePath);
  }

  public RelativePath createOutPath(String relativePath) {
    if (doGenerateFiles())
      return createCompileBinPath(relativePath);
    else
      return createParseBinPath(relativePath);
  }

  public List<Renaming> getRenamings() {
    return renamings;
  }
  
  public void setRenamings(List<Renaming> renamings) {
    this.renamings = renamings;
  }

  public boolean doGenerateFiles() {
    return generateFiles;
  }

  public void setGenerateFiles(boolean b) {
    this.generateFiles = b;
  }
}

@@ -1835,93 +1835,22 @@
 add(
-bin);%0A    this.includePath.add(stdlibDirPath);%0A    this.generateFiles = generateFiles
+stdlibDirPath)
 ;%0A  
@@ -1910,46 +1910,8 @@
 ();%0A
-      this.includePath.add(parseBin);%0A
     
@@ -1979,16 +1979,94 @@
 ;%0A    %7D%0A
+    this.generateFiles = !generateFiles;%0A    setGenerateFiles(generateFiles);%0A
   %7D%0A  %0A 
@@ -2366,17 +2366,44 @@
  return 
-b
+generateFiles ? bin : parseB
 in;%0A  %7D%0A
@@ -2456,15 +2456,40 @@
 .bin
+ 
 !=
+ 
 null
-)
+ && doGenerateFiles()) %7B
 %0A   
@@ -2527,26 +2527,8 @@
 ;%0A  
-  this.bin = bin;%0A
     
@@ -2549,16 +2549,42 @@
 d(bin);%0A
+    %7D%0A    this.bin = bin;%0A
   %7D%0A%0A  p
@@ -3414,130 +3414,8 @@
  %7D%0A%0A
-  private RelativePath createCompileBinPath(String relativePath) %7B%0A    return new RelativePath(bin, relativePath);%0A  %7D%0A  %0A
   pu
@@ -3534,22 +3534,21 @@
 %7D%0A  %0A  p
-rivate
+ublic
  Relativ
@@ -3555,32 +3555,27 @@
 ePath create
-ParseBin
+Out
 Path(String 
@@ -3622,214 +3622,18 @@
 ath(
-parseBin, relativePath);%0A  %7D%0A%0A  public RelativePath createOutPath(String relativePath) %7B%0A    if (doGenerateFiles())%0A      return createCompileBinPath(relativePath);%0A    else%0A      return createParseBinPath(
+getBin(), 
 rela
@@ -3918,24 +3918,257 @@
 oolean b) %7B%0A
+    if (this.generateFiles == b)%0A      return;%0A    %0A    if (this.generateFiles) %7B%0A      includePath.remove(bin);%0A      includePath.add(parseBin);%0A    %7D%0A    else %7B%0A      includePath.remove(parseBin);%0A      includePath.add(bin);%0A    %7D%0A
     this.gen

fix env initialization and result moving