package com.urbancode.air.plugin.scm;

import com.urbancode.air.*

import java.io.File;
import java.util.Date;
import java.util.regex.Pattern
import com.urbancode.commons.util.IO
import org.apache.commons.lang.math.RandomUtils;

abstract public class SCMStep {

    //**************************************************************************
    // CLASS
    //**************************************************************************
    static protected final String REPO_TYPE = 'accurev'
    static protected final SCMHelper scmHelper = new SCMHelper()
    static public String systemTemp = System.getProperty("java.io.tmpdir")
    
    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    String scmCommand = "accurev";

    String host = null;
    String username = null;
    String password = null;

    File directory;
//    boolean clean = false
    String streamName;
    String revision;
    Date date;
    private boolean loggedIn = false
    private File tempDir;
    
    final CommandHelper cmdHelper = new CommandHelper(directory);

    /**
     * Method to check if login is required and authenticate with provided credentials if needed/able
     */
    protected void login() {
        if (!username) {
            println "No user credentials provided. Skipping login detection and login."
            return
        }

        tempDir = new File(systemTemp, "accurev-" + RandomUtils.nextInt()).getAbsoluteFile()
        tempDir.mkdir()
        
        println "Setting ACCUREV_HOME to " + tempDir.getAbsolutePath()
        cmdHelper.addEnvironmentVariable("ACCUREV_HOME", tempDir.getAbsolutePath())
        
        boolean needsLogin = checkAuth()
        
        if (needsLogin) {
            // run login
            loggedIn = true
            
            if (username) {
                def loginCmd = [scmCommand, 'login']
                if (host) {
                    loginCmd << '-H' << host
                }
                
                // we use the -n because its the only way to ensure a session does not expire even when
                // using a unique ACCUREV_HOME
                loginCmd << '-n' << username << password ?: ''
                
                cmdHelper.runCommand("Logging In to AccuRev", loginCmd);
            }
            else {
                println "No username found, continuing with anonymous access";
            }
        }
    }
    
    protected boolean checkAuth() {
        def infoCommand = [scmCommand, 'info']
        if (host) {
            infoCommand << '-H' << host
        }
        def infoText = new ByteArrayOutputStream();

        cmdHelper.runCommand("Check if authenticated", infoCommand) { Process proc ->
            proc.out.close() // close stdin
            def out = new PrintStream(System.out, true);
            try {
                proc.waitForProcessOutput(infoText, out) // forward stdout and stderr to autoflushing output stream
            }
            finally {
                out.flush();
            }
            println infoText;
        }
        
        boolean needsLogin = false
        
        // Check if a login is required
        if (infoText =~ /(.*)(P|p)rincipal:\s*\(not logged in\)/) {
            needsLogin = true
        }
        
        return needsLogin
    }
    
    protected void logout() {
        try {
            if (loggedIn) {
                def logoutCmd = [scmCommand, "logout"]
                
                if (host) {
                    logoutCmd << "-H" << host
                }

                cmdHelper.runCommand("Logging Out of AccuRev", logoutCmd);
                
                loggedIn = false
            }
        }            
        finally {
            if (tempDir) {
                println "\nDeleting ACCUREV_HOME directory " + tempDir.getAbsolutePath() + "\n"
                IO.delete(tempDir);
            }
        }
    }
}
