package ca.ucalgary.seahawk.services;
 
import ca.ucalgary.seahawk.gui.MobyContentPane;
import ca.ucalgary.seahawk.gui.MobyServicesGUI;
import ca.ucalgary.seahawk.util.SeahawkOptions;
import ca.ucalgary.seahawk.util.HTMLUtils;
import ca.ucalgary.services.Registration;
import ca.ucalgary.services.util.PBERecorder;

import org.biomoby.client.CentralImpl;
import org.biomoby.shared.MobyService;

import javax.swing.JOptionPane;

import java.net.URL;
import java.util.Vector;
import java.util.logging.*;

/**
 * Simple interface methods to get information from the Daggoo service wrapper database, 
 * e.g. is this WSDL already available as Moby services?
 */
public class DaggooClient{
    private static Logger logger = Logger.getLogger(DaggooClient.class.getName());

    /**
     * The three outcomes possible from asking the user about the URL dropped on Seahawk.
     */
    public enum Action {WRAP, CALL, VIEW, NOTHING}
	
    public static boolean acceptAnExistingWrapper(URL u, MobyContentPane dropTargetPane, MobyServicesGUI servicesGUI){
	// by default, do not provide view vs. wrap option
	return acceptAnExistingWrapper(u, dropTargetPane, servicesGUI, false) != Action.WRAP;
	// all actions except wrap are handled by this method
    }

    /**
     * Presents the user with a dialog showing all Moby services (wrappers) that exist for the provided URL.
     * This method will handle calling of existing services and viewing the form.  Only a return of Action.WRAP
     * is actionable for the caller.
     *
     * @param u the URL containing the form/wsdl doc to wrap
     * @param dropTargetPane the Seahawk GUI element onto which the URL was dropped
     * @param giveViewOption provide extra option to just view the page in Seahawk, rather than wrap the service
     */
    public static Action acceptAnExistingWrapper(URL u, MobyContentPane dropTargetPane, 
						 MobyServicesGUI servicesGUI, boolean giveViewOption){
	// Before wrapping the WSDL, see if there are already services wrapping it (in Daggoo).
	// If so, ask the user if they want to use one of those instead.
	try{
	    String existingServices = HTMLUtils.getURLContents(new URL(PBERecorder.getProxyBaseUrl()+
								       "lookup/"+Registration.OP_SPEC_DOC_PARAM+
								       "/"+u));
	    Vector<String> choices = new Vector<String>();
	    if(existingServices != null && existingServices.length() != 0){
		String registryURL = SeahawkOptions.getRegistry() == null ? 
		    CentralImpl.getDefaultURL() :
		    SeahawkOptions.getRegistry().getEndpoint();
		for(String line: existingServices.split("\n")){
		    String[] fields = line.split("\t");
		    if(fields.length != 4){
			throw new Exception("Did not get lines with 4 tab-delimited fields " +
					    "from Daggoo lookup service.  The offending line is " + line);
		    }
		    if(!fields[1].equals(registryURL)){
			logger.log(Level.INFO, 
				   "Skipping service in different registry (" + 
				   fields[1] + ") than the current one in Seahawk (" +
				   registryURL + ")");
			continue;
		    }
		    choices.add(fields[3]+" ("+fields[2]+")");
		}
	    }
	    //todo: add "Don't show me this dialog again" option?
	    Object selectedValue = null;
	    if(!giveViewOption){
		if(choices.isEmpty()){
		    return Action.WRAP; // none in the registry we need
		}
		selectedValue = JOptionPane.showInputDialog(dropTargetPane,
							    "The services below wrap the same page as " +
							    "you just dragged into Seahawk.\n  Would you like to " +
							    "call one instead of wrapping the page again?",
							    "Existing Wrapper Services",
							    JOptionPane.INFORMATION_MESSAGE, null,
							    choices.toArray(), choices.get(0));
		if(selectedValue == null){
		    // cancel = wrap it yourself instead of using one of the service options presented
		    return Action.WRAP;
		}
		// Deconstruct the label built above
		String providerURI = ((String) selectedValue).replaceFirst("^.*\\((\\S+)\\).*$", "$1");
		String serviceName = ((String) selectedValue).replaceFirst("^(.*)\\s*\\(.*$", "$1");
		MobyService mobyService = dropTargetPane.getContentGUI().findService(providerURI, serviceName);
		// Launch the GUI to populate the service request (no initial data provided)
		servicesGUI.setupService(mobyService, null, null);
	    }
	    else{ // give user three options: call service, wrap service or view URL contents in Seahawk
		Action action = Action.NOTHING;
		if(choices.isEmpty()){ // still give option to wrap or view contents if no services exist
		    int choice = JOptionPane.showOptionDialog(dropTargetPane, 
							      "What would you like to do with this Web page?", "Wrap or View?",
							      JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE,
							      null, new String[]{"Create a service", "View page contents"}, 
							      "Create a service");
		    if(choice == JOptionPane.CLOSED_OPTION){
			return Action.NOTHING;
		    }
		    else if(choice == 0){
			return Action.WRAP;
		    }
		    else{ 
			action = Action.VIEW;
		    }
		}
		else{
		    
		}
		if(action == Action.VIEW){
		    // load the page for viewing.  Normally gotoURL would cause recursion on this method, so
		    // we disable wrapping temporarily to avoid this.
		    dropTargetPane.setWrappingEnabled(false);
		    dropTargetPane.gotoURL(u, true);
		    dropTargetPane.setWrappingEnabled(true);
		    return Action.VIEW;
		}
	    }
	    // todo: actually call service
	    System.err.println("Running the existing wrapper " + selectedValue);
	}
	catch(Exception e){
	    logger.log(Level.WARNING, "Cannot show the user existing service options", e);
	    return Action.VIEW;
	}
	return Action.CALL;  //if we got here, the user accepted an existing service
    }
}
