/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.axis2.tool.service.eclipse.ui;

import org.apache.axis2.tool.service.bean.WSDLAutoGenerateOptionBean;
import org.apache.axis2.tool.service.eclipse.plugin.ServiceArchiver;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;

import java.io.File;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class WSDLOptionsPage extends AbstractServiceWizardPage {

    private static final String SERVICE_WSDL_DEFAULT_NAME = "service.wsdl";
    private Text classNameTextBox;
    private Text outputFileNameTextBox;
    private Combo styleSelectionCombo;
    private Button searchDeclaredMethodsCheckBox;
    private Table table;
    
    private boolean dirty = false;
    
    public WSDLOptionsPage(){
        super("page6");
    }
    /* (non-Javadoc)
     * @see org.apache.axis2.tool.service.eclipse.ui.AbstractServiceWizardPage#initializeDefaultSettings()
     */
    protected void initializeDefaultSettings() {
       settings.put(PREF_WSDL_FILE_NAME,SERVICE_WSDL_DEFAULT_NAME);
       settings.put(PREF_WSDL_CLASS_NAME,"");
       settings.put(PREF_WSDL_STYLE_INDEX,0);

    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    public void createControl(Composite parent) {
        Composite container = new Composite(parent, SWT.NULL);
        GridLayout layout = new GridLayout();
        container.setLayout(layout);
        layout.numColumns = 3;
        layout.verticalSpacing = 9;

        // #########################################################

        Label label = new Label(container, SWT.NULL);
        label
                .setText(ServiceArchiver
                        .getResourceString("page6.fileName.label"));
        GridData gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = 2;
        outputFileNameTextBox = new Text(container, SWT.BORDER);
        outputFileNameTextBox.setLayoutData(gd);
        outputFileNameTextBox.setText(settings.get(PREF_WSDL_FILE_NAME));
        //###########################################################
        outputFileNameTextBox.setEnabled(false);//this text box is disbaled for
                                                // now
        //########################################################
        outputFileNameTextBox.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                handlFileNameModification();
            }
        });

        //########################################################
        gd = new GridData(GridData.FILL_HORIZONTAL);
        label = new Label(container, SWT.NULL);
        label.setText(ServiceArchiver.getResourceString("page6.class.label"));

        classNameTextBox = new Text(container, SWT.BORDER);
        classNameTextBox.setLayoutData(gd);
        classNameTextBox.setText(settings.get(PREF_WSDL_CLASS_NAME));
        classNameTextBox.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent e) {
                handleClassNameModification();
            }
        });

        gd = new GridData(GridData.FILL_HORIZONTAL);
        Button loadButton = new Button(container, SWT.PUSH);
        loadButton.setText("Load");
        loadButton.setLayoutData(gd);
        loadButton.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                updateTable();
            }

            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });

        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = 3;
        
        searchDeclaredMethodsCheckBox = new Button(container,SWT.CHECK);
        searchDeclaredMethodsCheckBox.setLayoutData(gd);
        searchDeclaredMethodsCheckBox.setText("List Declared Methods Only");
        searchDeclaredMethodsCheckBox.addSelectionListener(new SelectionListener(){
            public void widgetSelected(SelectionEvent e){
                updateDirtyStatus(true);//dirty
            }
            public void widgetDefaultSelected(SelectionEvent e){} 
        });
        
        // #####################################################
        label = new Label(container, SWT.NULL);
        label.setText(ServiceArchiver.getResourceString("page6.style.label"));

        gd = new GridData(GridData.FILL_HORIZONTAL);
        gd.horizontalSpan = 2;
        styleSelectionCombo = new Combo(container, SWT.DROP_DOWN | SWT.BORDER
                | SWT.READ_ONLY);
        styleSelectionCombo.setLayoutData(gd);
        populateStyleCombo();
        styleSelectionCombo.addSelectionListener(new SelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                settings.put(PREF_WSDL_STYLE_INDEX, styleSelectionCombo
                        .getSelectionIndex());
            }

            public void widgetDefaultSelected(SelectionEvent e) {
            }
        });
        
        gd = new GridData(GridData.FILL_BOTH);
        gd.horizontalSpan = 3;
        gd.verticalSpan = 5;
        
        table = new Table(container,SWT.SINGLE|SWT.FULL_SELECTION|SWT.CHECK);
        table.setLinesVisible(true);
        table.setHeaderVisible(true); 
        table.setLayoutData(gd);
        declareColumn(table,20,"");
        declareColumn(table,100,"Method Name");
        declareColumn(table,100,"Return Type");
        declareColumn(table,100,"Parameter Count");
        
        table.setVisible(false);
        
        setControl(container);

    }
    
    private void declareColumn(Table table, int width,String colName){
        TableColumn column = new TableColumn(table,SWT.NONE);
        column.setWidth(width);
        column.setText(colName);
    }
    
    
    private void populateStyleCombo() {
        styleSelectionCombo.add("Document");
        styleSelectionCombo.add("rpc");
        styleSelectionCombo.add("Wrapped");

        styleSelectionCombo.select(settings.getInt(PREF_WSDL_STYLE_INDEX));
        
    }
    
    private void updateTable() {
        //get a URL from the class file location
        try {
            String classFileLocation = getClassFileLocation();
            URL classFileURL = new File(classFileLocation).toURL();
            ClassLoader loader = new URLClassLoader(new URL[] { classFileURL });

            Class clazz = loader.loadClass(classNameTextBox.getText());
            Method[] methods = null;
            
            if (searchDeclaredMethodsCheckBox.getSelection()){
                methods = clazz.getDeclaredMethods();
            }else{
                methods = clazz.getMethods();
            }

            int methodCount = methods.length;
            if (methodCount > 0) {
                table.removeAll();
                TableItem[] items = new TableItem[methodCount]; // An item for each field
                for (int i = 0 ; i < methodCount; i++){
                   items[i] = new TableItem(table, SWT.NONE);
                   items[i].setText(1,methods[i].getName());
                   items[i].setText(2,methods[i].getReturnType().getName());
                   items[i].setText(3,methods[i].getParameterTypes().length+"");
                   items[i].setChecked(true);//check them all by default
                }
                table.setVisible(true);
                
                //update the dirty variable
               updateDirtyStatus(false);
               updateStatus(null);
            }

        } catch (MalformedURLException e) {
           updateStatus("Error : invalid location " +e.getMessage());
        } catch (ClassNotFoundException e) {
           updateStatus("Error : Class not found " + e.getMessage());
        }
    }
    private void handleClassNameModification(){
        String className = classNameTextBox.getText();
        settings.put(PREF_WSDL_CLASS_NAME, className);
        
        if (className==null || "".equals(className.trim())){
            updateStatus(ServiceArchiver.getResourceString("page6.error.classname1"));
        }else if (className.endsWith(".")){
            updateStatus(ServiceArchiver.getResourceString("page6.error.classname2"));
        }else{
            updateStatus(null);
        }
        
    }
    
    private void handlFileNameModification(){
        String wsdlFileName = outputFileNameTextBox.getText();
        settings.put(PREF_WSDL_FILE_NAME, wsdlFileName);
        
        if (wsdlFileName==null || "".equals(wsdlFileName.trim())){
            updateStatus(ServiceArchiver.getResourceString("page6.error.fileName1"));
        }else if (wsdlFileName.endsWith(".wsdl")){
            updateStatus(ServiceArchiver.getResourceString("page6.error.fileName2"));
        }else{
            updateStatus(null);
        }
        
    }
    private String getClassFileLocation(){
        ServiceArchiveWizard wizard = (ServiceArchiveWizard)getWizard();
        return wizard.getClassFileLocation();
    }
    
    public WSDLAutoGenerateOptionBean getBean(){
        WSDLAutoGenerateOptionBean optionBean = new WSDLAutoGenerateOptionBean();
        optionBean.setClassFileName(classNameTextBox.getText());
        optionBean.setOutputFileName(outputFileNameTextBox.getText());
        optionBean.setStyle(styleSelectionCombo.getItem(styleSelectionCombo.getSelectionIndex()));
        return optionBean;
    }
    
    private void updateDirtyStatus(boolean status){
        dirty = status;
        if (table.isVisible()){
            table.setEnabled(!status);
        }
        setPageComplete(!status);
    }
    
	protected boolean getWizardComplete() {
		return false;
	}
}
