package com.vasoftware.sf.plugin;

import com.collabnet.ce.soap60.webservices.ClientSoapStubFactory;
import com.collabnet.ce.soap60.webservices.cemain.RelationshipSoapDO;
import com.collabnet.ce.soap60.webservices.tracker.ArtifactSoapDO;
import com.collabnet.ce.soap60.webservices.tracker.ITrackerAppSoap;
import com.collabnet.ctf.events.Asynchronous;
import com.collabnet.ctf.events.EventContext;
import com.collabnet.ctf.events.EventListener;
import com.collabnet.ctf.events.SoapVersion;
import com.vasoftware.sf.common.logger.Logger;

import javax.xml.namespace.QName;
import java.io.InputStream;
import java.util.Properties;
import org.apache.axis.AxisFault;

/**
 * This listener listens TeamForge relationship event type and on all operations.
 * Adds a comment to source artifact upon association operations
 */
@EventListener(version = SoapVersion.SOAP_60)
public class AsynchronousRelationshipEventListener {

    private static final String WEB_SERVICE_ENDPOINT_PROPERTY = "webServiceEndpoint";
    private static final String FORMATSTRING_PROPERTY = "formatString";
    private static final String PROPERTIES_FILE = "META-INF/config.properties";
    private static String defaultWebserviceEndpoint = "http://localhost:8080";
    private static String defaultFormatString = "<OPERATION> association with artifact <TARGET>\n <DESCRIPTION>";
    private static final Logger log = Logger.getLogger(AsynchronousRelationshipEventListener.class);
    private boolean initialized = false;
    
    public  AsynchronousRelationshipEventListener() {
      initialize();
    }
    
    private synchronized void initialize() {
        if (initialized ) {
            return;
        }
        initialized = true;
        
        // read format string
        try {
            InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(PROPERTIES_FILE);
            Properties prop = new Properties();
            prop.load(inputStream);
            String formatString = prop.getProperty(FORMATSTRING_PROPERTY);
            if (formatString != null) {
                defaultFormatString = formatString;
            }
            String webServiceEndpoint = prop.getProperty(WEB_SERVICE_ENDPOINT_PROPERTY);
            if (webServiceEndpoint != null) {
                defaultWebserviceEndpoint = webServiceEndpoint;
            }
        } catch (Exception e) {
            log.error("While reading the properties file " + PROPERTIES_FILE + " an error occured", e);
        }
    }

    @Asynchronous(topic = "object.Relationship.*", user = "system")
    public void addCommentToArtfOnAssociation(final EventContext context) throws Exception {    
        
        RelationshipSoapDO relationShip = (RelationshipSoapDO) context.getUpdatedData();
        String originId = relationShip.getOriginKey();
        String targetId = relationShip.getTargetKey();
        String description = relationShip.getDescription();
        String operation = context.getEventOperation();
        if (operation.equals("create")) {
            operation = "created ";
        } else if (operation.equals("update")) {
            operation = "updated ";
        } else if (operation.equals("delete")) {
            operation = "deleted  ";
        } else if (operation.equals("move")) {
            operation = "moved  ";
        }
        ITrackerAppSoap trackerClient = (ITrackerAppSoap) ClientSoapStubFactory.getSoapStub(ITrackerAppSoap.class,
                defaultWebserviceEndpoint);
        
        String comment = defaultFormatString.replace("<OPERATION>", operation);
        comment = comment.replace("<DESCRIPTION>", description);
        comment = comment.replace("<USER>", context.getUsername());
        
        if (originId.startsWith("artf")) {
            String finalComment = comment.replace("<TARGET>", targetId);
            finalComment = finalComment.replace("<SOURCE>", originId);
            
            boolean finishedUpdate = false;
            int numberOfTries = 0;
            while (!finishedUpdate && numberOfTries++ < 10) {   
                try {
                    ArtifactSoapDO artifact = trackerClient.getArtifactData(context.getSessionKey(), originId);
                    trackerClient.setArtifactData(context.getSessionKey(), artifact, finalComment, null,
                            null, null);
                    finishedUpdate = true;
                } catch (AxisFault e) {
                   QName faultCode = e.getFaultCode();
                   if (!faultCode.getLocalPart().equals("VersionMismatchFault")) {
                       throw e;
                   }
                }
            }
        }
        
        if (targetId.startsWith("artf")) {
            String finalComment = comment.replace("<TARGET>", originId);
            finalComment = finalComment.replace("<SOURCE>", targetId);
            boolean finishedUpdate = false;
            int numberOfTries = 0;
            while (!finishedUpdate && numberOfTries++ < 10) {   
                try {
                    ArtifactSoapDO artifact = trackerClient.getArtifactData(context.getSessionKey(), targetId);
                    trackerClient.setArtifactData(context.getSessionKey(), artifact, finalComment, null,
                            null, null);
                    finishedUpdate = true;
                } catch (AxisFault e) {
                   QName faultCode = e.getFaultCode();
                   if (!faultCode.getLocalPart().equals("VersionMismatchFault")) {
                       throw e;
                   }
                }
            }
        }
    }
}
