package com.urbancode.air.plugin.scm

import com.urbancode.air.*
import com.urbancode.air.plugin.scm.changelog.*

import java.text.SimpleDateFormat
import java.util.List;
import java.util.regex.Matcher
import java.util.regex.Pattern

public class SCMQuietPeriod extends SCMChangelog {
    
    //**************************************************************************
    // CLASS
    //**************************************************************************

    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    
    // Clientspec Creation Variables
    boolean createNewClientSpec
    boolean isUsingTemplate
    String templateName
    String clientspec
    
    // Changeset Variables
    final SimpleDateFormat PERFORCE_CHANGELOG_OUT_DATE = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
    final Pattern CHANGE_SUMMARY_PATTERN = ~'(?m)^Change \\d+ by (\\S+)@\\S+ on (\\d+/\\d+/\\d+ \\d+:\\d+:\\d+)'
    
    public def execute() {
        this.login()
        
        def creatingClientSpec = createNewClientSpec || isUsingTemplate
        if (creatingClientSpec) {
            createClientSpec()
        }
        
        getClientspecInfo()
        
        def logOutput = super.runLogCommand()
        def changeSets = super.parseChangesets(logOutput)
        Date latestDate = getLatestChangeDate(changeSets)
        
        if (creatingClientSpec) {
            deleteClientSpec()
        }
        
        return latestDate
    }
    
    public void createClientSpec() {
        if (isUsingTemplate) {
            def command = this.createP4BaseCommand()
            command << 'client' << '-o' << '-t' << templateName << client
            ch.runCommand("Getting Clientspec Template", command) { Process proc ->
                proc.out.close() // close stdin
                proc.consumeProcessErrorStream(out)
                clientspec = proc.text
            }
        }
        
        // modify the root in the clientspec config to reflect the directoryOffset if
        // one was specified in the command
        clientspec = modifyClientSpecConfigRoot(clientspec, dirOffset)
        
        // run the process
        def createClientCommand = createP4BaseCommand()
        createClientCommand << 'client' << '-i'
        ch.runCommand('Create Clientspec', createClientCommand) { Process proc ->
            proc.consumeProcessOutput(out, out)
            proc.withWriter{ it << clientspec} // pipe clientspec to child process stdIn and close the stream afterwards
            proc.out.close()
        }
    }
    
    public def getLatestChangeDate(List<ChangeSet> changeSets) {
        Date latestChangeDate
        
        changeSets.each{ ChangeSet changeSet ->
            if (changeSet.date > latestChangeDate) {
                latestChangeDate = changeSet.date
            }
        }
        
        return latestChangeDate
    }
    
    public void deleteClientSpec() {
        def deleteClientCommand = createP4BaseCommand()
        
        deleteClientCommand << 'client' << '-d'
//        if (isForceDelete) {
            deleteClientCommand << '-f'
//        }
        deleteClientCommand << client
        ch.runCommand('P4 Delete ClientSpec', deleteClientCommand)
    }
    
    /**
    * replace path in a configspec with given path
    */
    def modifyClientSpecConfigRoot = {def config, def newRoot ->
        if (!config) {
            return config
        }
        else if (!newRoot) {
           return config.replaceAll(/(?mi)Root:.*$/, Matcher.quoteReplacement("Root: ${new File('.').canonicalPath}"))
        }
        return config.replaceAll(/(?mi)Root:.*$/, Matcher.quoteReplacement("Root: ${new File('.', newRoot).canonicalPath}"))
    }
}