#Linux 'Don't know why' work arround.
BEGIN{
    my $pwd = `pwd`;
    push(@INC,substr($pwd,0,length($pwd)-1)."/lib");
}
use YAML;

sub action_replicate{
    my $out = " -o taktuk=' ' -o  connector=' ' -o error='\"ERR(\$host)  - \$line\\n\"' -o output='\"\$line: OK\\n\"' -o status=' '";
    printf("Running Commands... \n");
    open FILE, "replicate.sh" or die $!;
    my $lines = <FILE>;
    
    printf("Running $commands");
    
    for my $dep (@deployee){
        $path =  lookup($dep,"path"); # it is the on-site place
        $nodes{$dep}{"command"} = "
            $lines
        ";
    }
    taktuk($out,\@deployee);
    
    printf("DONE\n");
}

sub lookup{
    my ($name,$key) = @_;
    return $nodes{$name}{$key}; 
}

#Loads the topology from $topology.yml file
sub action_topology{
    
    #Tries to open the yml file.
	open my $fh, '<', "config/$topology".'.yml'
		or die "FAILURE: can't open $topology.yml file: $!";
    
    # Reads the file
	my $yml = do { local $/; <$fh> }; 
    #Loads the yml file into a hash reference 
	my $mach = Load($yml);
	#Dereferences into the hash 
    %nodes = %$mach;
    #Keep tracking of known shares
    my %share;
        
    #Ignoring default override

    for my $node ( keys %nodes ) {
        # Marks the node as grm machine
        $nodes{$node}{"installgrm"} = $default->{"installgrm"} if (not defined $nodes{$node}{"installgrm"});
        # Marks the node as lrm machine
        $nodes{$node}{"installlrm"} = $default->{"installlrm"} if (not defined $nodes{$node}{"installlrm"});
        # Says wich machine is this machine grm
        $nodes{$node}{"grm"       } = $default->{"grm"       } if (not defined $nodes{$node}{"grm"       });
        # Says wich is the path for installation
        $nodes{$node}{"path"      } = $default->{"path"      } if (not defined $nodes{$node}{"path"      });
        # Says wich is the java path for installation
        $nodes{$node}{"java"      } = $default->{"java"      } if (not defined $nodes{$node}{"java"      });                                                             
        # If it's not a shared node, than it is a deployee, else, if its note yet on the share node, it is deployee
        # Wich means, this insert each non shared node + the shared nodes only once per share, and marks the share
        if (not defined $nodes{$node}{"shared"    }){
            $nodes{$node}{"shared"    } = $default->{"shared"    };
            push @deployee, $node;
        } elsif (not defined $share{$nodes{$node}{"shared"}}){
            push @deployee, $node;
            $share{$nodes{$node}{"shared"}} = $node;
        }
        
        push @machines,$node;
    }

}

#Creates a package with integrade and dependencies
#   -Tar Warning is annoying
sub action_pack{
    printf("Packing Integrade and Deps... \n");
    if ( -e "packs/deploy.tar.gz") {
        printf("Integrade exists\n");
    } else {
        system("cd packs/deps && make clean > /dev/null && cd -  > /dev/null");
        system("cd packs > /dev/null && tar czf deploy.tar.gz  ../../integrade > /dev/null && cd  -  > /dev/null");
    }
    if ( -e "packs/deps.tar.gz") {
        printf("Deps exists\n");
    } else {
        system("cd packs  > /dev/null&& tar czf deps.tar.gz deps > /dev/null && cd - > /dev/null");
    }
}

#Ping machines to see if they work
sub action_ping{
    my $out = " -o taktuk=' ' -o  connector=' ' -o error='\"ERR(\$host)  - \$line\\n\"' -o output='\"\$line: OK\\n\"' -o status=' '";
    
    for my $dep (@deployee){
        $nodes{$dep}{"command"} = "hostname";
    }
    
    printf "Look if all hosts are available...\n";
    taktuk($out,\@deployee);
    printf "DONE\n";
}

# Remove the deployed structure and clean installation files
sub action_clean{
    my $out = " -o error='\"ERR(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";
    
    for my $dep (@deployee){
        $nodes{$dep}{"command"} = "rm -Rf deploy.log deploy.tar.gz deps.tar.gz /tmp/log"
    }
    
    print("Cleaning local files.... ");
    system("rm -Rf packs/deps.tar.gz packs/deploy.tar.gz");
    print("DONE\n");
    print("Clening remote files... ");
    taktuk($out,\@deployee);
    print("DONE\n");
    
}

# Remove Integrade from the set of nodes
sub action_uninstall{
    
    my $path;
    my $out = " -o error='\"ERR(\$host)  - \$line\\n\"' -o output=' ' -o status=' '"; 
    
    for my $dep (@deployee){
        $path = lookup($dep,"path");
        $nodes{$dep}{"command"} = "
            rm -Rf deploy.log deploy.tar.gz deps.tar.gz $path/integrade/ $path/deps /tmp/log $path/deploy.tar.gz $path/deps.tar.gz 
            ";
    }
    
    
    print("Removing Integrade... ");
    taktuk($out,\@deployee);
    print("DONE\n");
}

sub action_deploy{
    my $out = " -o error='\"ERR(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";
    
    printf("Deploying this machines: ".join(" ",@deployee));    
    taktuk($out,\@deployee,1);
    printf("\nDONE\n");
}

sub action_deploydeps{
    my $out = " -o error='\"ERR(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";
    
    printf("Deploying the DEPS on this machines: ".join(" ",@deployee));    
    taktuk($out,\@deployee,2); # 2 = Deploy only the deps
    printf("\nDONE\n");
}


sub action_deps{
    my $out = " -o error='\"WARNING(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";
    
    my $java;
    my $grm;
    my $install_path;
    my $path;
    
    printf("Building Dependencies (This may take a while)...\n");    
    
    for my $dep (@deployee){
        $java = lookup($dep,"java");
        $grm = lookup($dep,"grm");
        $install_path = lookup($dep,"path"); # it is the shared place 
        $path =  lookup($dep,"path"); # it is the on-site place
        $nodes{$dep}{"command"} = "
            cp deps.tar.gz $install_path >> /tmp/log/deploy-`hostname`.log &&
            cd $install_path && tar zxvf deps.tar.gz >> /tmp/log/tar-`hostname`.log &&
            cd deps &&
            make clean &&
            make all
            ";
    }
    taktuk($out,\@deployee);
    printf("DONE\n");
}

sub action_install{
    my $out = " -o error='\"WARNING(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";
    
    my $java;
    my $grm;
    my $install_path;
    my $path;
    
    printf("Installing (This may take a while)...\n");    

    for my $dep (@deployee){
        $java = lookup($dep,"java");
        $grm = lookup($dep,"grm");
        $install_path = lookup($dep,"path"); # it is the shared place 
        $path =  lookup($dep,"path"); # it is the on-site place
        $nodes{$dep}{"command"} = "
            cp deploy.tar.gz $path >> /tmp/log/deploy-`hostname`.log &&
            cd $path && tar zxvf deploy.tar.gz >> /tmp/log/tar-`hostname`.log &&
            ln -s $install_path/deps $path/integrade/deps &&
            cd $path/integrade &&
            ./scripts/tkmake.sh `pwd` $grm $java >> /tmp/log/tkmake-`hostname`.log
            ";
    }
    taktuk($out,\@deployee);
    
    printf("DONE\n Cleaning information files...");
    for my $dep (@deployee){
        $path =  lookup($dep,"path"); # it is the on-site place
        $nodes{$dep}{"command"} = "
            rm -Rf $path/deploy.tar.gz $path/deps.tar.gz deploy.tar.gz deps.tar.gz 
        ";
    }
    taktuk($out,\@deployee);
    
    printf("DONE\n");
}

sub action_installportal{
    my $out = " -o error='\"WARNING(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";

	printf("Installing portal...\n");
	$grm = lookup($deployee[0],"grm");
	$java = lookup($grm,"java");
	$path = lookup($grm,"path");
	$nodes{$grm}{"command"} = "
		cd $path/integrade ;
        ./scripts/tkmake-portal.sh `pwd` $grm $java >> /tmp/log/tkmake-portal-`hostname`.log
		";
	push(@grms,$grm);
	taktuk($out,\@grms);

	printf("DONE\n");
}

# issue grm first

sub action_start{
    my $out = " -o error='\"WARNING(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";
    
    for my $dep (@deployee){
        $grm = lookup($dep,"grm");
        $path =  lookup($dep,"path"); # it is the on-site place
        $nodes{$dep}{"command"} = "
            cd $path/integrade ;
            ./scripts/tkstart.sh `pwd` $grm
            ";
    }
    
    print "Integrade is beeing started.... (because of bug in Integrade scripts this call never finishes...)\n";
    print "Type CTRL+C\n";
    taktuk($out,\@deployee);
}

sub action_stop{
    my $out = " -o error='\"WARNING(\$host)  - \$line\\n\"' -o output=' ' -o status=' '";
    
    for my $dep (@deployee){
        $java = "/usr/lib/jvm/java-6-sun/";
        $grm = lookup($dep,"grm");
        $install_path = lookup($dep,"path"); # it is the shared place 
        $path =  lookup($dep,"path"); # it is the on-site place
        $nodes{$dep}{"command"} = "
            $path/integrade/stopservices.sh all
            ";
    }
    
    print "Stopping all services...... ";
    taktuk($out,\@deployee);
    print "DONE\n";
}

sub action_check{
    my $is;
    my $grm;
    my $path;
    my $java;
    my $shared;
    printf ("Reading $topology.yml\n");
    for my $node ( keys %nodes ) {
        $is = "";
        if ($nodes{$node}{"installgrm"}){
           $is = $is."grm ";
        }
        if ($nodes{$node}{"installlrm"}){
            $is = $is."lrm";
        }
        
        $grm    = $nodes{$node}{"grm"       }; 
        $path   = $nodes{$node}{"path"      }; 
        $java   = $nodes{$node}{"java"      };                                                          
        $shared = $nodes{$node}{"shared"    };
        
        print "$node($is), GRM $grm will install in $path with java at $java\n and shared as $shared\n"; 
    }

}


sub action_exp1{
	system('cd tools; ./generate.rb;');
	my @duration = [];
	my $start,$end;
	my @n = (1,2,4,8,16,32,64,128);
	for ($i = 0; $i < 20; $i++){
		$duration[$i] = {};
		for my $mach (@n){
			$topology = "sophia".$mach;
			print $toopology;
			$start = time();
			action_topology();
			$end = time();
			$duration[$i]{"topology$mach"} = $start - $end;
			$start = time();						
		    action_clean();
			action_replicate();
			$end = time();
			$duration[$i]{"clean$mach"} = $start - $end;
			$start = time();			
		    action_pack();
			$end = time();
			$duration[$i]{"pack$mach"} = $start - $end;
			$start = time();			
		    action_deploy();
			$end = time();
			$duration[$i]{"deploy$mach"} = $start - $end;		
			$start = time();			
		    action_deps();
			$end = time();
			$duration[$i]{"deps$mach"} = $start - $end;
			$start = time();			
		    action_install();
			$end = time();
			$duration[$i]{"install$mach"} = $start - $end;
			$start = time();			
		    action_uninstall();
			$end = time();
			$duration[$i]{"uninstall$mach"} = $start - $end;
			$start = time();		
		}
	    open(YAMLFILE,">results.yaml");
    	    print YAMLFILE Dump($duration);
	    close(YAMLFILE);
	}
}

sub action_installdeps{
    action_ping();
    action_clean();
    action_pack();
    action_deploydeps();
    action_deps();
}

sub action_all{
#    action_check();
    action_ping();
    action_clean();
    action_pack();
    action_deploy();
    action_deps();
    action_install();
}
sub action_purge{
    action_stop();
    action_uninstall();
    action_clean();
}

1;
