/*
This file is licensed under the terms of the Globus Toolkit Public
License, found at http://www.globus.org/toolkit/download/license.html.
*/

package condor.gahp.gt3;

import condor.gahp.*;

import org.globus.ogsa.impl.core.service.ServicePropertiesImpl;
import org.globus.ogsa.NotificationSinkCallback;
import org.gridforum.ogsi.ExtensibilityType;
//import org.globus.ogsa.base.gram.types.Fault;
import org.globus.ogsa.base.gram.types.FaultType;
import org.globus.ogsa.base.gram.types.JobStateType;
import org.globus.ogsa.base.gram.types.JobStatusType;
import org.gridforum.ogsi.ServiceDataValuesType;
import org.globus.ogsa.utils.AnyHelper;
import org.globus.gram.internal.GRAMConstants;
import javax.xml.namespace.QName;
import org.globus.ogsa.base.gram.service.ManagedJobServiceGridLocator;

public class JobListener extends ServicePropertiesImpl implements NotificationSinkCallback {

    public final GahpInterface gahp;
    public final int requestId;
    public final String jobContact;
    public String callbackId;

    //private int lastState = -1;

    public JobListener(int requestId, String jobContact, GahpInterface gahp) {
        this.gahp=gahp;
        this.requestId = requestId;
        this.jobContact = jobContact;
    }

    public void deliverNotification(ExtensibilityType message) {
        // Return <req id> <job contact> <job state> <error code>

        JobStatusType jobStatus = null;
        JobStateType jobState = null; 
        FaultType fault = null;
        int jobStateAsInt = -1;
        try {
            jobStatus = getJobStatusFromServiceData(message);
            jobState = jobStatus.getJobState();
            if (jobState.equals(JobStateType.Failed)) {
                ExtensibilityType faultExt = jobStatus.getFault();

                if (faultExt != null) {
                    System.err.println("faultExtensibility != null");
                    Object faultObj = AnyHelper.getAsSingleObject(faultExt);

                    if (faultObj != null && faultObj instanceof FaultType) {
                        fault = (FaultType) faultObj;
                    }
                }
            }
            jobStateAsInt =  getStatusStringAsInt(jobState.toString());
        }
        catch (Exception e) {
            gahp.addResult(
                           requestId, 
                           new String[] {
                               ""+jobContact,
                               ""+(1),
                               "callback processing error"
                           }
                           );
        }
        
        gahp.addResult(
            requestId, 
            new String[] {
                ""+jobContact,
                ""+getStatusStringAsInt(jobState.toString()),
                (fault!=null)?(fault.getDescription()[0]):"NULL"
            }
        ); 

    }

    public static int getStatusStringAsInt(String statusString) {
        if (statusString.equals(JobStateType._Pending)) {
            return GRAMConstants.STATUS_PENDING;
        } else if (statusString.equals(JobStateType._Active)) {
            return GRAMConstants.STATUS_ACTIVE;
        } else if (statusString.equals(JobStateType._Done)) {
            return GRAMConstants.STATUS_DONE;
        } else if (statusString.equals(JobStateType._Failed)) {
            return GRAMConstants.STATUS_FAILED;
        } else if (statusString.equals(JobStateType._Suspended)) {
            return GRAMConstants.STATUS_SUSPENDED;
        } else if (statusString.equals("Unsubmitted")) {
            return GRAMConstants.STATUS_UNSUBMITTED;
        } else if (statusString.equals(JobStateType._StageIn)) {
            return GRAMConstants.STATUS_STAGE_IN;
        } else if (statusString.equals(JobStateType._StageOut)) {
            return GRAMConstants.STATUS_STAGE_OUT;
        }
        return -1;
    }
    
    // from GramJob
    private JobStatusType getJobStatusFromServiceData(
                            ExtensibilityType serviceData) throws Exception {

        ServiceDataValuesType serviceDataValues = (ServiceDataValuesType)
            AnyHelper.getAsServiceDataValues(serviceData);

        checkAtLeastOne(serviceDataValues, 
                        new QName(org.globus.ogsa.base.gram.StartType.getTypeDesc().
                                  getXmlType().getNamespaceURI(),
                                  "ManagedJobState"));

        JobStatusType jobStatus = (JobStatusType)AnyHelper.
            getAsSingleObject(serviceDataValues, JobStatusType.class);

        return jobStatus;
    }

    private void checkAtLeastOne(ServiceDataValuesType serviceDataValues,
                                 QName qNameForQuery) {
        //check
        if (serviceDataValues == null || serviceDataValues.get_any() == null) {
            throw new RuntimeException(
                    "Querying by QName for\n" +
                    qNameForQuery.getNamespaceURI() + ":" +
                    qNameForQuery.getLocalPart() + "\n" +
                    "returned no such service data element (SDE), " +
                    "in violation of the schema declaration of that SDE.");
        }

    }
}
