/*
* 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 org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.DefaultHttpClient

import com.urbancode.air.*
import com.urbancode.air.plugin.scm.changelog.*
import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder
import com.urbancode.commons.util.IO


public class SCMChangelog {

    //**************************************************************************
    // CLASS
    //**************************************************************************
    final protected static String REPO_TYPE = "FileSystem"
    
    //**************************************************************************
    // INSTANCE
    //**************************************************************************

    // changelog boundaries
    Date startDate = null
    Date endDate = null
    String changesUrl = null
    File dir = null

    // filters for changeset
    final ChangeSetFilter changeSetFilter = new ChangeSetFilter()
    Map<Date, ChangeSet> changeSets

    /**
     *
     * @return xml document of changes
     */
    public def execute() {
        changeSets = new HashMap<ChangeSet>()
        
        getChangeHistory(dir)
        
        // Construct xml message and send to server
        if (changeSets) {
            ChangeSetXMLHelper xmlHelper = new ChangeSetXMLHelper()
            xmlHelper.repoType = REPO_TYPE
            String xml = xmlHelper.toXML(changeSets, dir)
            sendPostRequest(xml)
        }
        else {
            println "No changes detected"
        }
    }
    
    private void getChangeHistory(File file) {
        if (file.isDirectory()) {
            File[] fileArray = file.listFiles()
            for (int i = 0; i < fileArray.length; i++) {
                if (fileArray[i].isDirectory()) {
                    getChangeHistory(fileArray[i])
                }
                else {
                    Date lastModified = new Date(fileArray[i].lastModified())
                    if (startDate.before(lastModified) && endDate.after(lastModified)) {
                        ChangeSet changeSet = changeSets.get(lastModified)
                        
                        if (!changeSet) {
                            changeSet = new ChangeSet()
                            changeSet.date = lastModified
                            changeSet.fileSet << fileArray[i]
                            
                            if (changeSet.hasAllowedPath(changeSetFilter)) {
                                changeSets.put(lastModified, changeSet)
                            }
                        }
                        else {
                            changeSet.fileSet << fileArray[i]
                            
                            if (!changeSet.hasAllowedPath(changeSetFilter)) {
                                changeSet.fileSet.remove(fileArray[i])
                            }
                        }
                    }
                }
            }
        }
    }
    
    private void sendPostRequest(String xml) {
        // construct the URL with property replacements
        String url = changesUrl
        def authToken = System.getenv("AUTH_TOKEN")
        
        println "Sending request to $url"

        // Debug/testing stub
       if (url.startsWith("file://")) {
           File xmlOut = new File(dir, "xmlOut.xml")
           xmlOut << xml
       }
       else {
           HttpClientBuilder clientBuilder = new HttpClientBuilder();
           clientBuilder.setTrustAllCerts(true);
           DefaultHttpClient client = clientBuilder.buildClient();
           
           HttpPost postMethod = new HttpPost(url);
           if (authToken) {
               postMethod.setHeader("Authorization-Token", authToken)
               postMethod.setHeader("Content-Type", "application/xml")
           }
          
           println "Sending ${changeSets.size()} changes"
           postMethod.setEntity(new StringEntity(xml));
       
           def httpResponse = client.execute(postMethod)
           def responseCode = httpResponse.getStatusLine().getStatusCode()
           if (isGoodResponseCode(responseCode)) {
               IO.copy(postMethod.getEntity().getContent(), System.out)
               println ""
           }
           else {
               IO.copy(postMethod.getEntity().getContent(), System.err)
               throw new RuntimeException("Failed to upload source changes. StatusCode: ${responseCode}")
           }
       }
    }
    
    private boolean isGoodResponseCode(int responseCode) {
        return responseCode >= 200 && responseCode < 300
    }
}