import EDU.neu.ccs.demeter.dj.*;
import com.objectspace.jgl.*;

class Dos {
  public ClassGraph cg;
  public Directory root;
  public Directory curdir; // current directory

  // going in up direction in dir tree
  public Strategy strat_moveup;
  public TraversalGraph tg_moveup;

  // going in down direction in dir tree
  public Strategy strat_movedowndir;
  public TraversalGraph tg_movedowndir;

  // find file
  public Strategy strat_find;
  public TraversalGraph tg_find;

  // reset Parent Directory (for recursive copy)
  public Strategy strat_reset;
  public TraversalGraph tg_reset;

  // remove file/directory ( in the current directory )
  public Strategy strat_remove;
  public TraversalGraph tg_remove;	

  public Dos() {
	super();

	cg = new ClassGraph();
	
	// strategies	
	strat_moveup = new Strategy("from Directory bypassing DiskItem to Directory");
	tg_moveup = TraversalGraph.compute( cg, strat_moveup );

	strat_movedowndir = new Strategy("from Directory bypassing {File,SLink,ParentList} to Directory");
	tg_movedowndir = TraversalGraph.compute( cg, strat_movedowndir );

	strat_find = new Strategy("from Directory bypassing { SLink,ParentList } to File");
	tg_find = TraversalGraph.compute( cg, strat_find );

	strat_reset = new Strategy("from Directory bypassing {-> ParentList,mget_dir,Directory } to ParentList");
	tg_reset = TraversalGraph.compute( cg, strat_reset );

	strat_remove = new Strategy("from Directory bypassing { File,SLink,Directory,ParentList} to DiskItem");
	tg_remove = TraversalGraph.compute( cg, strat_remove );

	root = new Directory();
	root.set_name("C:");
	curdir = root;

//	printPrompt();
  }

  public void printPrompt() {
	tg_moveup.traverse( curdir, new Visitor_prompt() );
  }
  
  public void echo( String name ) {
	printPrompt();
	System.out.print( name );
  }

  public void makeDirectory( String name ) {
	printPrompt();
	System.out.print( "mkdir " + name );
	Directory newDir = new Directory( curdir );
	newDir.set_name( name );
	curdir.set_content( new NEList( newDir, curdir.get_content() ) );
  }

  public void createEmptyFile( String name ) {
	printPrompt();
	System.out.print( "touch " + name );
	File newFile = new File( curdir );
	newFile.set_name( name );
	curdir.set_content( new NEList( newFile, curdir.get_content() ) );
  }	

  public void changeDirectory( String name ) {
	printPrompt();
	System.out.print( "cd " + name );
	if ( name == ".." )
	{
		Visitor_CDUp visitor = new Visitor_CDUp( curdir );
		tg_moveup.traverse( curdir, visitor );
		if ( visitor.parent != null ) curdir = visitor.parent;
	}
	else
	{
		Visitor_CDDown visitor = new Visitor_CDDown( name );
		tg_movedowndir.traverse( curdir, visitor );
		if ( visitor.target != null ) curdir = visitor.target;
	}
  }

  public void findAllFiles( String name ) {
	printPrompt();
	System.out.print( "find " + name );
	Visitor_FIND visitor = new Visitor_FIND( name );
	tg_find.traverse( root, visitor );
  }

  public void diskUsage()
  {
	printPrompt();
	System.out.print( "du" );
	Visitor_DiskUsage visitor = new Visitor_DiskUsage();
	tg_movedowndir.traverse( root, visitor );
  }

  public void diskUsageAll()
  {
	printPrompt();
	System.out.print( "du all" );
	Visitor_DiskUsageAll visitor = new Visitor_DiskUsageAll();
	tg_find.traverse( root, visitor );
  }

  File findSpecFile( String name ) // full path name
  {
	Visitor_FindSpecFile visitor = new Visitor_FindSpecFile( name );
	tg_find.traverse( root, visitor );
	return visitor.file;
  }

  public void symbolicLink( String fullFileName, String linkName )
  {
	printPrompt();
	System.out.print( "ln -s "+fullFileName+" "+linkName );
	File file = findSpecFile( fullFileName );
	if ( file == null )
	{
		System.out.println(" ");
		System.out.println("Specified file hasn't been found");
	}
	else
	{
		SLink newSLink = new SLink( linkName, fullFileName, curdir );
		curdir.set_content( new NEList( newSLink, curdir.get_content() ) );
	}
  }		

  Directory findSpecDir( String name ) // full path directory
  {
	Visitor_FindSpecDir visitor = new Visitor_FindSpecDir( name );
	tg_movedowndir.traverse( root, visitor );
	return visitor.dir;
  }	

  public void recursiveCopy( String fullDirName, String newName ) // copies directory fullDirName into newName in currentDirectory
  {
	printPrompt();
	System.out.print( "cp -r "+fullDirName+" "+newName );
	Directory dir = findSpecDir( fullDirName );
	if ( dir == null )
	{
		System.out.println(" ");
		System.out.println("Specified directory hasn't been found");
		return;
	}
	
	WrapDiskItem w = new WrapDiskItem();
	dir.copy( w );
	Directory newDir = (Directory)(w.di);
	if ( newDir == null )
	{
		System.out.println(" ");
		System.out.println("Directory creation problem");
		return;
	}

	newDir.set_name( newName );
	curdir.set_content( new NEList( newDir, curdir.get_content() ) );

	Visitor_reset visitor = new Visitor_reset( curdir );
	tg_reset.traverse( newDir, visitor );
  }

  public void remove( String name ) // remove file/directory with the name (short form)
  {
	printPrompt();
	System.out.print( "rm "+name );
	Visitor_remove visitor = new Visitor_remove( name );
	tg_remove.traverse( curdir, visitor );
  }	

}