/*
 * JBoss, Home of Professional Open Source
 * Copyright 2009, Red Hat Middleware LLC, and others contributors as indicated
 * by the @authors tag. All rights reserved.
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License, v. 2.1.
 * This program is distributed in the hope that it will be useful, but WITHOUT A
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License,
 * v.2.1 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 */
package org.jboss.soa.bpel.runtime.engine.ode;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.iapi.*;
import org.jboss.soa.bpel.runtime.engine.PartnerChannel;
import org.jboss.soa.bpel.runtime.integration.ServerConfigFactory;
import org.jboss.soa.bpel.runtime.ws.*;


import javax.wsdl.Definition;
import javax.wsdl.PortType;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLReader;
import javax.xml.namespace.QName;
import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.UUID;

/**
 * Delegates endpoint creation to a JAX-WS web service stack,
 * leveraging the AS deployer framework.
 *
 * @author Heiko.Braun
 */
public class JAXWSBindingContext implements BindingContext
{
  protected final Log log = LogFactory.getLog(getClass());

  private BPELEngineImpl engine;
  private EndpointManager endpointManager;
  private UDDIRegistration uddiRegistration = null;

  public JAXWSBindingContext(BPELEngineImpl server) {
    this.engine = server;
    this.endpointManager = new EndpointManager(this.engine);
   
  }
  
  public org.apache.ode.bpel.iapi.EndpointReference getEndpoint(QName serviceName, String portName) {
	return(endpointManager.maintains(serviceName, portName));	
  }


  public org.apache.ode.bpel.iapi.EndpointReference activateMyRoleEndpoint(QName processId, Endpoint myRoleEndpoint)
  {
    log.info("Activate my role endpoint: "+myRoleEndpoint);

    org.apache.ode.bpel.iapi.EndpointReference ref =
        endpointManager.maintains(myRoleEndpoint.serviceName, myRoleEndpoint.portName);

    if(ref!=null)
    {
      // might happen when processes are retired.
      // See https://jira.jboss.org/jira/browse/RIFTSAW-57
      log.warn("Endpoint does already exist: "
          + myRoleEndpoint.serviceName + "/"+myRoleEndpoint.portName);
    }
    else
    {
      WSDLReference wsdlReference = new WSDLHelper().createWSDLReference(engine, processId, 
    		  myRoleEndpoint.serviceName, myRoleEndpoint.portName);

      try
      {
        final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        String endpointId = UUID.randomUUID().toString();

        EndpointMetaData endpointMD = new EndpointMetaData(
            myRoleEndpoint.serviceName, myRoleEndpoint.portName,
            processId, endpointId
        );

        ref = endpointManager.createEndpoint(endpointMD, wsdlReference, classLoader);

      }
      catch (Throwable e)
      {
        throw new ContextException("Failed to activate endpoint", e);
      }
    }

    return(ref);
  }

 
  public void deactivateMyRoleEndpoint(Endpoint myRoleEndpoint)
  {
    log.info("Deactivate my role endpoint: "+myRoleEndpoint);

    org.apache.ode.bpel.iapi.EndpointReference ref =
        endpointManager.maintains(myRoleEndpoint.serviceName, myRoleEndpoint.portName);

    if(null==ref)
    {
      // might happen when processes are retired.
      // See https://jira.jboss.org/jira/browse/RIFTSAW-57
      log.warn("Endpoint doesn't exist (Has it been undeployed before?): "
          + myRoleEndpoint.serviceName + "/"+myRoleEndpoint.portName);
    }
    else
    {
      try
      {
        endpointManager.removeEndpoint(myRoleEndpoint.serviceName, myRoleEndpoint.portName);
      }
      catch (Throwable e)
      {
        throw new ContextException("Failed to deactivate endpoint", e);
      }
    }
  }

  public PartnerRoleChannel createPartnerRoleChannel(QName processId, PortType portType,
                                                     Endpoint initialPartnerEndpoint) {
    // NOTE: This implementation assumes that the initial value of the
    // partner role determines the binding.
	
    
    
    // TODO: TEAM_ODE:
    // 1) try to obtain EPR from wsdl, associated with service and port name - see createExternalService
    //							code below for possible use of ProcessConf to get external service WSDL
    // 2) if not found, then do uddi lookup using service and port name
    // 3) if multiple EPRs found, use some mechanism for selecting
    // 4) find transport layer associated with the EPR
    // 5) create channel on transport layer associated with EPR

    String endpointId = UUID.randomUUID().toString();
    EndpointMetaData endpointMD = new EndpointMetaData(
        initialPartnerEndpoint.serviceName, initialPartnerEndpoint.portName,
        processId, endpointId
    );
    
    ProcessConf pconf=engine._store.getProcessConfiguration(processId);

    try
    {
      PartnerChannel channel = endpointManager.createClient(endpointMD, engine , pconf);

      return new PartnerRoleChannelImpl(channel);
    }
    catch (Throwable t)
    {
      throw new ContextException("Failed to create partner channel", t);
    }
  }

 
  public long calculateSizeofService(
      org.apache.ode.bpel.iapi.EndpointReference arg0) {
    // TODO Auto-generated method stub
    return 0;
  }

}
