/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* (c) Copyright IBM Corporation 2012, 2014. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/
package com.urbancode.air.plugin.scm

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

import java.util.Date;
import java.util.TimeZone;
import java.text.SimpleDateFormat


public class SCMQuietPeriod extends SCMChangelog {

    //**************************************************************************
    // CLASS
    //**************************************************************************

    //**************************************************************************
    // INSTANCE
    //**************************************************************************
    
    /**
     *
     * @return date of the last change
     */
    public def execute() {
        SVN_DATE = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S Z")
        SVN_DATE.timeZone = TimeZone.getTimeZone("GMT")
        
        SVN_DATE_OUT_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.S'Z'")
        SVN_DATE_OUT_FORMAT.timeZone = TimeZone.getTimeZone("GMT")
        
        directory.mkdirs();
        
        println "Validating revisions"
        validate()
        
        initCheckoutPath();
        
        parseTrueOffset()
        
        // Get Change Log Output
        def logOutput = runLogCommand()
        def latestDate = parseLog(logOutput)
        
        return latestDate
    }
    
    private String runLogCommand() {
        def logCommand = [this.scmCommand, 'log', '--non-interactive', '--no-auth-cache', '--verbose', '--xml']

        if (username) {
            logCommand << "--username" << this.username
            
            if (password) {
                logCommand << "--password" << this.password
            }
        }

        // Order range as  end:start so that limiting will give the one closest to end-date
        if (startRevision || endRevision) {
            logCommand << '--revision'
            def revArg = new StringBuilder()

            if (endRevision) {
                revArg += endRevision
            }
            if (startRevision) {
                if (revArg.length()) {
                    revArg += ':'
                }
                
                revArg += startRevision
            }
            
            logCommand << revArg
        }

        logCommand << (svnRoot + this.checkoutPath)

        def logOutput = null
        cmdHelper.runCommand('Getting Changelog', logCommand) { Process proc ->
            proc.consumeProcessErrorStream(System.out)
            proc.out.close()
            logOutput = proc.text
            println logOutput
           
            if(!(logOutput?.trim())) {
                println("No Changes Found");
            }
        }
        return logOutput
    }
    
    private def parseLog(String logOutput) {
        // the result change set date
        Date latestChangeDate = null;

        groovy.util.slurpersupport.GPathResult log = new XmlSlurper().parseText(logOutput);
        
        log.logentry.each{ svnchangeset ->
            ChangeSet changeSet = new ChangeSet();
            String dateText = svnchangeset.date[0].text().replaceFirst('[0-9]{3}Z$', 'Z')
            def svnDate = SVN_DATE_OUT_FORMAT.parse(dateText)

            changeSet.id = svnchangeset.@revision.text();
            changeSet.user = svnchangeset.author[0].text();
            changeSet.message = svnchangeset.msg[0].text();
            changeSet.date = svnDate
            
            svnchangeset.paths[0].path.each() { path ->
                def operation = path.@action.text()
                def filename = path.text()

                ChangeSetFileEntry entry = new ChangeSetFileEntry();
                entry.revision = changeSet.id;
                entry.type = operation
                entry.path = filename;
                changeSet.fileSet << entry;
            }

            boolean allowAuthor = changeSet.hasAllowedAuthor(changeSetFilter);
            boolean allowAnyPaths = changeSet.hasAllowedPath(changeSetFilter);
            if (allowAuthor && allowAnyPaths) {
                latestChangeDate = changeSet.date;
            }
            else {
                def message = new StringBuilder("Changeset ${changeSet.id} skipped because ")
                if (!allowAuthor) {
                    message << "it has excluded author ${changeSet.user}"
                }
                if (!allowAuthor && !allowAnyPaths) {
                    message << " and "
                }
                if (!allowAnyPaths) {
                    message << "it contains only excluded file paths (${changeSet.fileSet.collect{it.path}})"
                }
                println message
            }
        }

        return latestChangeDate;
    }
}
