/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.hdt.ui.wizards;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.apache.hadoop.conf.Configuration;
import org.apache.hdt.core.cluster.ConfProp;
import org.apache.hdt.core.cluster.HadoopCluster;
import org.apache.hdt.ui.cluster.ServerRegistry;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
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.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.eclipse.swt.widgets.Text;

/**
 * Wizard for editing the settings of a Hadoop location
 * 
 * The wizard contains 3 tabs: General, Tunneling and Advanced. It edits
 * parameters of the location member which either a new location or a copy of
 * an existing registered location.
 */

public class HadoopLocationWizard extends WizardPage {

  Image circle;

  /**
   * The location effectively edited by the wizard. This location is a copy
   * or a new one.
   */
  private HadoopCluster location;

  /**
   * The original location being edited by the wizard (null if we create a
   * new instance).
   */
  private HadoopCluster original;

  /**
   * New Hadoop location wizard
   */
  public HadoopLocationWizard() {
    super("Hadoop Server", "New Hadoop Location", null);

    this.original = null;
    this.location = new HadoopCluster();
    this.location.setLocationName("");
  }

  /**
   * Constructor to edit the parameters of an existing Hadoop server
   * 
   * @param server
   */
  public HadoopLocationWizard(HadoopCluster server) {
    super("Create a new Hadoop location", "Edit Hadoop Location", null);

    this.original = server;
    this.location = new HadoopCluster(server);
  }

  /**
   * Performs any actions appropriate in response to the user having pressed
   * the Finish button, or refuse if finishing now is not permitted.
   * 
   * @return the created or updated Hadoop location
   */

  public HadoopCluster performFinish() {
    try {
      if (this.original == null) {
        // New location
        Display.getDefault().syncExec(new Runnable() {
          public void run() {
            ServerRegistry.getInstance().addServer(
                HadoopLocationWizard.this.location);
          }
        });
        return this.location;

      } else {
        // Update location
        final String originalName = this.original.getLocationName();
        this.original.load(this.location);

        Display.getDefault().syncExec(new Runnable() {
          public void run() {
            ServerRegistry.getInstance().updateServer(originalName,
                HadoopLocationWizard.this.location);
          }
        });
        return this.original;

      }
    } catch (Exception e) {
      e.printStackTrace();
      setMessage("Invalid server location values", IMessageProvider.ERROR);
      return null;
    }
  }

  /**
   * Validates the current Hadoop location settings (look for Hadoop
   * installation directory).
   * 
   */
  private void testLocation() {
    setMessage("Not implemented yet", IMessageProvider.WARNING);
  }

  /**
   * Location is not complete (and finish button not available) until a host
   * name is specified.
   * 
   * @inheritDoc
   */
  @Override
  public boolean isPageComplete() {

    {
      String locName = location.getConfProp(ConfProp.PI_LOCATION_NAME);
      if ((locName == null) || (locName.length() == 0)
          || locName.contains("/")) {

        setMessage("Bad location name: "
            + "the location name should not contain "
            + "any character prohibited in a file name.", WARNING);

        return false;
      }
    }

    {
      String master = location.getConfProp(ConfProp.PI_JOB_TRACKER_HOST);
      if ((master == null) || (master.length() == 0)) {

        setMessage("Bad master host name: "
            + "the master host name refers to the machine "
            + "that runs the Job tracker.", WARNING);

        return false;
      }
    }

    {
      String jobTracker = location.getConfProp(ConfProp.JOB_TRACKER_URI);
      String[] strs = jobTracker.split(":");
      boolean ok = (strs.length == 2);
      if (ok) {
        try {
          int port = Integer.parseInt(strs[1]);
          ok = (port >= 0) && (port < 65536);
        } catch (NumberFormatException nfe) {
          ok = false;
        }
      }
      if (!ok) {
        setMessage("The job tracker information ("
            + ConfProp.JOB_TRACKER_URI.name + ") is invalid. "
            + "This usually looks like \"host:port\"", WARNING);
        return false;
      }
    }

    {
      String fsDefaultURI = location.getConfProp(ConfProp.FS_DEFAULT_URI);
      try {
        URI uri = new URI(fsDefaultURI);
      } catch (URISyntaxException e) {

        setMessage("The default file system URI is invalid. "
            + "This usually looks like \"hdfs://host:port/\" "
            + "or \"file:///dir/\"", WARNING);
      }
    }

    setMessage("Define the location of a Hadoop infrastructure "
        + "for running MapReduce applications.");
    return true;
  }

  /**
   * Create the wizard
   */
  /* @inheritDoc */
  public void createControl(Composite parent) {
    setTitle("Define Hadoop location");
    setDescription("Define the location of a Hadoop infrastructure "
        + "for running MapReduce applications.");

    Composite panel = new Composite(parent, SWT.FILL);
    GridLayout glayout = new GridLayout(2, false);
    panel.setLayout(glayout);

    TabMediator mediator = new TabMediator(panel);
    {
      GridData gdata = new GridData(GridData.FILL_BOTH);
      gdata.horizontalSpan = 2;
      mediator.folder.setLayoutData(gdata);
    }
    this.setControl(panel /* mediator.folder */);
    {
      final Button btn = new Button(panel, SWT.NONE);
      btn.setText("&Load from file");
      btn.setEnabled(false);
      btn.setToolTipText("Not yet implemented");
      btn.addListener(SWT.Selection, new Listener() {
        public void handleEvent(Event e) {
          // TODO
        }
      });
    }
    {
      final Button validate = new Button(panel, SWT.NONE);
      validate.setText("&Validate location");
      validate.setEnabled(false);
      validate.setToolTipText("Not yet implemented");
      validate.addListener(SWT.Selection, new Listener() {
        public void handleEvent(Event e) {
          testLocation();
        }
      });
    }
  }

  private interface TabListener {
    void notifyChange(ConfProp prop, String propValue);
  }

  /*
   * Mediator pattern to keep tabs synchronized with each other and with the
   * location state.
   */

  private class TabMediator {
    TabFolder folder;

    private Set<TabListener> tabs = new HashSet<TabListener>();

    TabMediator(Composite parent) {
      folder = new TabFolder(parent, SWT.NONE);
      tabs.add(new TabMain(this));
      tabs.add(new TabAdvanced(this));
    }

    /**
     * Access to current configuration settings
     * 
     * @param propName the property name
     * @return the current property value
     */
    String get(String propName) {
      return location.getConfProp(propName);
    }

    String get(ConfProp prop) {
      return location.getConfProp(prop);
    }

    /**
     * Implements change notifications from any tab: update the location
     * state and other tabs
     * 
     * @param source origin of the notification (one of the tree tabs)
     * @param propName modified property
     * @param propValue new value
     */
    void notifyChange(TabListener source, final ConfProp prop,
        final String propValue) {
      // Ignore notification when no change
      String oldValue = location.getConfProp(prop);
      if ((oldValue != null) && oldValue.equals(propValue))
        return;

      location.setConfProp(prop, propValue);
      Display.getDefault().syncExec(new Runnable() {
        public void run() {
          getContainer().updateButtons();
        }
      });

      this.fireChange(source, prop, propValue);

      /*
       * Now we deal with dependencies between settings
       */
      final String jobTrackerHost =
          location.getConfProp(ConfProp.PI_JOB_TRACKER_HOST);
      final String jobTrackerPort =
          location.getConfProp(ConfProp.PI_JOB_TRACKER_PORT);
      final String nameNodeHost =
          location.getConfProp(ConfProp.PI_NAME_NODE_HOST);
      final String nameNodePort =
          location.getConfProp(ConfProp.PI_NAME_NODE_PORT);
      final boolean colocate =
          location.getConfProp(ConfProp.PI_COLOCATE_MASTERS)
              .equalsIgnoreCase("yes");
      final String jobTrackerURI =
          location.getConfProp(ConfProp.JOB_TRACKER_URI);
      final String fsDefaultURI =
          location.getConfProp(ConfProp.FS_DEFAULT_URI);
      final String socksServerURI =
          location.getConfProp(ConfProp.SOCKS_SERVER);
      final boolean socksProxyEnable =
          location.getConfProp(ConfProp.PI_SOCKS_PROXY_ENABLE)
              .equalsIgnoreCase("yes");
      final String socksProxyHost =
          location.getConfProp(ConfProp.PI_SOCKS_PROXY_HOST);
      final String socksProxyPort =
          location.getConfProp(ConfProp.PI_SOCKS_PROXY_PORT);

      Display.getDefault().syncExec(new Runnable() {
        public void run() {
          switch (prop) {
            case PI_JOB_TRACKER_HOST: {
              if (colocate)
                notifyChange(null, ConfProp.PI_NAME_NODE_HOST,
                    jobTrackerHost);
              String newJobTrackerURI =
                  String.format("%s:%s", jobTrackerHost, jobTrackerPort);
              notifyChange(null, ConfProp.JOB_TRACKER_URI, newJobTrackerURI);
              break;
            }
            case PI_JOB_TRACKER_PORT: {
              String newJobTrackerURI =
                  String.format("%s:%s", jobTrackerHost, jobTrackerPort);
              notifyChange(null, ConfProp.JOB_TRACKER_URI, newJobTrackerURI);
              break;
            }
            case PI_NAME_NODE_HOST: {
              String newHDFSURI =
                  String.format("hdfs://%s:%s/", nameNodeHost, nameNodePort);
              notifyChange(null, ConfProp.FS_DEFAULT_URI, newHDFSURI);

              // Break colocation if someone force the DFS Master
              if (!colocate && !nameNodeHost.equals(jobTrackerHost))
                notifyChange(null, ConfProp.PI_COLOCATE_MASTERS, "no");
              break;
            }
            case PI_NAME_NODE_PORT: {
              String newHDFSURI =
                  String.format("hdfs://%s:%s/", nameNodeHost, nameNodePort);
              notifyChange(null, ConfProp.FS_DEFAULT_URI, newHDFSURI);
              break;
            }
            case PI_SOCKS_PROXY_HOST: {
              String newSocksProxyURI =
                  String.format("%s:%s", socksProxyHost, socksProxyPort);
              notifyChange(null, ConfProp.SOCKS_SERVER, newSocksProxyURI);
              break;
            }
            case PI_SOCKS_PROXY_PORT: {
              String newSocksProxyURI =
                  String.format("%s:%s", socksProxyHost, socksProxyPort);
              notifyChange(null, ConfProp.SOCKS_SERVER, newSocksProxyURI);
              break;
            }
            case JOB_TRACKER_URI: {
              String[] strs = jobTrackerURI.split(":", 2);
              String host = strs[0];
              String port = (strs.length == 2) ? strs[1] : "";
              notifyChange(null, ConfProp.PI_JOB_TRACKER_HOST, host);
              notifyChange(null, ConfProp.PI_JOB_TRACKER_PORT, port);
              break;
            }
            case FS_DEFAULT_URI: {
              try {
                URI uri = new URI(fsDefaultURI);
                if (uri.getScheme().equals("hdfs")) {
                  String host = uri.getHost();
                  String port = Integer.toString(uri.getPort());
                  notifyChange(null, ConfProp.PI_NAME_NODE_HOST, host);
                  notifyChange(null, ConfProp.PI_NAME_NODE_PORT, port);
                }
              } catch (URISyntaxException use) {
                // Ignore the update!
              }
              break;
            }
            case SOCKS_SERVER: {
              String[] strs = socksServerURI.split(":", 2);
              String host = strs[0];
              String port = (strs.length == 2) ? strs[1] : "";
              notifyChange(null, ConfProp.PI_SOCKS_PROXY_HOST, host);
              notifyChange(null, ConfProp.PI_SOCKS_PROXY_PORT, port);
              break;
            }
            case PI_COLOCATE_MASTERS: {
              if (colocate)
                notifyChange(null, ConfProp.PI_NAME_NODE_HOST,
                    jobTrackerHost);
              break;
            }
            case PI_SOCKS_PROXY_ENABLE: {
              if (socksProxyEnable) {
                notifyChange(null, ConfProp.SOCKET_FACTORY_DEFAULT,
                    "org.apache.hadoop.net.SocksSocketFactory");
              } else {
                notifyChange(null, ConfProp.SOCKET_FACTORY_DEFAULT,
                "org.apache.hadoop.net.StandardSocketFactory");
              }
              break;
            }
          }
        }
      });

    }

    /**
     * Change notifications on properties (by name). A property might not be
     * reflected as a ConfProp enum. If it is, the notification is forwarded
     * to the ConfProp notifyChange method. If not, it is processed here.
     * 
     * @param source
     * @param propName
     * @param propValue
     */
    void notifyChange(TabListener source, String propName, String propValue) {

      ConfProp prop = ConfProp.getByName(propName);
      if (prop != null)
        notifyChange(source, prop, propValue);

      location.setConfProp(propName, propValue);
    }

    /**
     * Broadcast a property change to all registered tabs. If a tab is
     * identified as the source of the change, this tab will not be notified.
     * 
     * @param source TODO
     * @param prop
     * @param value
     */
    private void fireChange(TabListener source, ConfProp prop, String value) {
      for (TabListener tab : tabs) {
        if (tab != source)
          tab.notifyChange(prop, value);
      }
    }

  }

  /**
   * Create a SWT Text component for the given {@link ConfProp} text
   * configuration property.
   * 
   * @param listener
   * @param parent
   * @param prop
   * @return
   */
  private Text createConfText(ModifyListener listener, Composite parent,
      ConfProp prop) {

    Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
    GridData data = new GridData(GridData.FILL_HORIZONTAL);
    text.setLayoutData(data);
    text.setData("hProp", prop);
    text.setText(location.getConfProp(prop));
    text.addModifyListener(listener);

    return text;
  }

  /**
   * Create a SWT Checked Button component for the given {@link ConfProp}
   * boolean configuration property.
   * 
   * @param listener
   * @param parent
   * @param prop
   * @return
   */
  private Button createConfCheckButton(SelectionListener listener,
      Composite parent, ConfProp prop, String text) {

    Button button = new Button(parent, SWT.CHECK);
    button.setText(text);
    button.setData("hProp", prop);
    button.setSelection(location.getConfProp(prop).equalsIgnoreCase("yes"));
    button.addSelectionListener(listener);

    return button;
  }

  /**
   * Create editor entry for the given configuration property. The editor is
   * a couple (Label, Text).
   * 
   * @param listener the listener to trigger on property change
   * @param parent the SWT parent container
   * @param prop the property to create an editor for
   * @param labelText a label (null will defaults to the property name)
   * 
   * @return a SWT Text field
   */
  private Text createConfLabelText(ModifyListener listener,
      Composite parent, ConfProp prop, String labelText) {

    Label label = new Label(parent, SWT.NONE);
    if (labelText == null)
      labelText = prop.name;
    label.setText(labelText);

    return createConfText(listener, parent, prop);
  }

  /**
   * Create an editor entry for the given configuration name
   * 
   * @param listener the listener to trigger on property change
   * @param parent the SWT parent container
   * @param propName the name of the property to create an editor for
   * @param labelText a label (null will defaults to the property name)
   * 
   * @return a SWT Text field
   */
  private Text createConfNameEditor(ModifyListener listener,
      Composite parent, String propName, String labelText) {

    {
      ConfProp prop = ConfProp.getByName(propName);
      if (prop != null)
        return createConfLabelText(listener, parent, prop, labelText);
    }

    Label label = new Label(parent, SWT.NONE);
    if (labelText == null)
      labelText = propName;
    label.setText(labelText);

    Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
    GridData data = new GridData(GridData.FILL_HORIZONTAL);
    text.setLayoutData(data);
    text.setData("hPropName", propName);
    text.setText(location.getConfProp(propName));
    text.addModifyListener(listener);

    return text;
  }

  /**
   * Main parameters of the Hadoop location:
   * <li> host and port of the Map/Reduce master (Job tracker)
   * <li> host and port of the DFS master (Name node)
   * <li> SOCKS proxy
   */
  private class TabMain implements TabListener, ModifyListener,
      SelectionListener {

    TabMediator mediator;

    Text locationName;

    Text textJTHost;

    Text textNNHost;

    Button colocateMasters;

    Text textJTPort;

    Text textNNPort;

    Text userName;

    Button useSocksProxy;

    Text socksProxyHost;

    Text socksProxyPort;

    TabMain(TabMediator mediator) {
      this.mediator = mediator;
      TabItem tab = new TabItem(mediator.folder, SWT.NONE);
      tab.setText("General");
      tab.setToolTipText("General location parameters");
      tab.setImage(circle);
      tab.setControl(createControl(mediator.folder));
    }

    private Control createControl(Composite parent) {

      Composite panel = new Composite(parent, SWT.FILL);
      panel.setLayout(new GridLayout(2, false));

      GridData data;

      /*
       * Location name
       */
      {
        Composite subpanel = new Composite(panel, SWT.FILL);
        subpanel.setLayout(new GridLayout(2, false));
        data = new GridData();
        data.horizontalSpan = 2;
        data.horizontalAlignment = SWT.FILL;
        subpanel.setLayoutData(data);

        locationName =
            createConfLabelText(this, subpanel, ConfProp.PI_LOCATION_NAME,
                "&Location name:");
      }

      /*
       * Map/Reduce group
       */
      {
        Group groupMR = new Group(panel, SWT.SHADOW_NONE);
        groupMR.setText("Map/Reduce Master");
        groupMR.setToolTipText("Address of the Map/Reduce master node "
            + "(the Job Tracker).");
        GridLayout layout = new GridLayout(2, false);
        groupMR.setLayout(layout);
        data = new GridData();
        data.verticalAlignment = SWT.FILL;
        data.horizontalAlignment = SWT.CENTER;
        data.widthHint = 250;
        groupMR.setLayoutData(data);

        // Job Tracker host
        Label label = new Label(groupMR, SWT.NONE);
        label.setText("Host:");
        data =
            new GridData(GridData.BEGINNING, GridData.CENTER, false, true);
        label.setLayoutData(data);

        textJTHost =
            createConfText(this, groupMR, ConfProp.PI_JOB_TRACKER_HOST);
        data = new GridData(GridData.FILL, GridData.CENTER, true, true);
        textJTHost.setLayoutData(data);

        // Job Tracker port
        label = new Label(groupMR, SWT.NONE);
        label.setText("Port:");
        data =
            new GridData(GridData.BEGINNING, GridData.CENTER, false, true);
        label.setLayoutData(data);

        textJTPort =
            createConfText(this, groupMR, ConfProp.PI_JOB_TRACKER_PORT);
        data = new GridData(GridData.FILL, GridData.CENTER, true, true);
        textJTPort.setLayoutData(data);
      }

      /*
       * DFS group
       */
      {
        Group groupDFS = new Group(panel, SWT.SHADOW_NONE);
        groupDFS.setText("DFS Master");
        groupDFS.setToolTipText("Address of the Distributed FileSystem "
            + "master node (the Name Node).");
        GridLayout layout = new GridLayout(2, false);
        groupDFS.setLayout(layout);
        data = new GridData();
        data.horizontalAlignment = SWT.CENTER;
        data.widthHint = 250;
        groupDFS.setLayoutData(data);

        colocateMasters =
            createConfCheckButton(this, groupDFS,
                ConfProp.PI_COLOCATE_MASTERS, "Use M/R Master host");
        data = new GridData();
        data.horizontalSpan = 2;
        colocateMasters.setLayoutData(data);

        // Job Tracker host
        Label label = new Label(groupDFS, SWT.NONE);
        data = new GridData();
        label.setText("Host:");
        label.setLayoutData(data);

        textNNHost =
            createConfText(this, groupDFS, ConfProp.PI_NAME_NODE_HOST);

        // Job Tracker port
        label = new Label(groupDFS, SWT.NONE);
        data = new GridData();
        label.setText("Port:");
        label.setLayoutData(data);

        textNNPort =
            createConfText(this, groupDFS, ConfProp.PI_NAME_NODE_PORT);
      }

      {
        Composite subpanel = new Composite(panel, SWT.FILL);
        subpanel.setLayout(new GridLayout(2, false));
        data = new GridData();
        data.horizontalSpan = 2;
        data.horizontalAlignment = SWT.FILL;
        subpanel.setLayoutData(data);

        userName =
            createConfLabelText(this, subpanel, ConfProp.PI_USER_NAME,
                "&User name:");
      }

      // SOCKS proxy group
      {
        Group groupSOCKS = new Group(panel, SWT.SHADOW_NONE);
        groupSOCKS.setText("SOCKS proxy");
        groupSOCKS.setToolTipText("Address of the SOCKS proxy to use "
            + "to connect to the infrastructure.");
        GridLayout layout = new GridLayout(2, false);
        groupSOCKS.setLayout(layout);
        data = new GridData();
        data.horizontalAlignment = SWT.CENTER;
        data.horizontalSpan = 2;
        data.widthHint = 250;
        groupSOCKS.setLayoutData(data);

        useSocksProxy =
            createConfCheckButton(this, groupSOCKS,
                ConfProp.PI_SOCKS_PROXY_ENABLE, "Enable SOCKS proxy");
        data = new GridData();
        data.horizontalSpan = 2;
        useSocksProxy.setLayoutData(data);

        // SOCKS proxy host
        Label label = new Label(groupSOCKS, SWT.NONE);
        data = new GridData();
        label.setText("Host:");
        label.setLayoutData(data);

        socksProxyHost =
            createConfText(this, groupSOCKS, ConfProp.PI_SOCKS_PROXY_HOST);

        // SOCKS proxy port
        label = new Label(groupSOCKS, SWT.NONE);
        data = new GridData();
        label.setText("Port:");
        label.setLayoutData(data);

        socksProxyPort =
            createConfText(this, groupSOCKS, ConfProp.PI_SOCKS_PROXY_PORT);
      }

      // Update the state of all widgets according to the current values!
      reloadConfProp(ConfProp.PI_COLOCATE_MASTERS);
      reloadConfProp(ConfProp.PI_SOCKS_PROXY_ENABLE);
      reloadConfProp(ConfProp.PI_JOB_TRACKER_HOST);

      return panel;
    }

    /**
     * Reload the given configuration property value
     * 
     * @param prop
     */
    private void reloadConfProp(ConfProp prop) {
      this.notifyChange(prop, location.getConfProp(prop));
    }

    public void notifyChange(ConfProp prop, String propValue) {
      switch (prop) {
        case PI_JOB_TRACKER_HOST: {
          textJTHost.setText(propValue);
          break;
        }
        case PI_JOB_TRACKER_PORT: {
          textJTPort.setText(propValue);
          break;
        }
        case PI_LOCATION_NAME: {
          locationName.setText(propValue);
          break;
        }
        case PI_USER_NAME: {
          userName.setText(propValue);
          break;
        }
        case PI_COLOCATE_MASTERS: {
          if (colocateMasters != null) {
            boolean colocate = propValue.equalsIgnoreCase("yes");
            colocateMasters.setSelection(colocate);
            if (textNNHost != null) {
              textNNHost.setEnabled(!colocate);
            }
          }
          break;
        }
        case PI_NAME_NODE_HOST: {
          textNNHost.setText(propValue);
          break;
        }
        case PI_NAME_NODE_PORT: {
          textNNPort.setText(propValue);
          break;
        }
        case PI_SOCKS_PROXY_ENABLE: {
          if (useSocksProxy != null) {
            boolean useProxy = propValue.equalsIgnoreCase("yes");
            useSocksProxy.setSelection(useProxy);
            if (socksProxyHost != null)
              socksProxyHost.setEnabled(useProxy);
            if (socksProxyPort != null)
              socksProxyPort.setEnabled(useProxy);
          }
          break;
        }
        case PI_SOCKS_PROXY_HOST: {
          socksProxyHost.setText(propValue);
          break;
        }
        case PI_SOCKS_PROXY_PORT: {
          socksProxyPort.setText(propValue);
          break;
        }
      }
    }

    /* @inheritDoc */
    public void modifyText(ModifyEvent e) {
      final Text text = (Text) e.widget;
      final ConfProp prop = (ConfProp) text.getData("hProp");
      Display.getDefault().syncExec(new Runnable() {
        public void run() {
          mediator.notifyChange(TabMain.this, prop, text.getText());
        }
      });
    }

    /* @inheritDoc */
    public void widgetDefaultSelected(SelectionEvent e) {
      this.widgetSelected(e);
    }

    /* @inheritDoc */
    public void widgetSelected(SelectionEvent e) {
      final Button button = (Button) e.widget;
      final ConfProp prop = (ConfProp) button.getData("hProp");

      Display.getDefault().syncExec(new Runnable() {
        public void run() {
          // We want to receive the update also!
          mediator.notifyChange(null, prop, button.getSelection() ? "yes"
              : "no");
        }
      });
    }

  }

  private class TabAdvanced implements TabListener, ModifyListener {
    TabMediator mediator;

    private Composite panel;

    private Map<String, Text> textMap = new TreeMap<String, Text>();

    TabAdvanced(TabMediator mediator) {
      this.mediator = mediator;
      TabItem tab = new TabItem(mediator.folder, SWT.NONE);
      tab.setText("Advanced parameters");
      tab.setToolTipText("Access to advanced Hadoop parameters");
      tab.setImage(circle);
      tab.setControl(createControl(mediator.folder));

    }

    private Control createControl(Composite parent) {
      ScrolledComposite sc =
          new ScrolledComposite(parent, SWT.BORDER | SWT.H_SCROLL
              | SWT.V_SCROLL);

      panel = new Composite(sc, SWT.NONE);
      sc.setContent(panel);

      sc.setExpandHorizontal(true);
      sc.setExpandVertical(true);

      sc.setMinSize(640, 480);

      GridLayout layout = new GridLayout();
      layout.numColumns = 2;
      layout.makeColumnsEqualWidth = false;
      panel.setLayout(layout);
      panel.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true,
          true, 1, 1));

      // Sort by property name
      Configuration config = location.getConfiguration();
      SortedMap<String, String> map = new TreeMap<String, String>();
      Iterator<Entry<String, String>> it = config.iterator();
      while (it.hasNext()) {
        Entry<String, String> entry = it.next();
        map.put(entry.getKey(), entry.getValue());
      }

      for (Entry<String, String> entry : map.entrySet()) {
        Text text = createConfNameEditor(this, panel, entry.getKey(), null);
        textMap.put(entry.getKey(), text);
      }

      sc.setMinSize(panel.computeSize(SWT.DEFAULT, SWT.DEFAULT));

      return sc;
    }

    public void notifyChange(ConfProp prop, final String propValue) {
      Text text = textMap.get(prop.name);
      text.setText(propValue);
    }

    public void modifyText(ModifyEvent e) {
      final Text text = (Text) e.widget;
      Object hProp = text.getData("hProp");
      final ConfProp prop = (hProp != null) ? (ConfProp) hProp : null;
      Object hPropName = text.getData("hPropName");
      final String propName =
          (hPropName != null) ? (String) hPropName : null;

      Display.getDefault().syncExec(new Runnable() {
        public void run() {
          if (prop != null)
            mediator.notifyChange(TabAdvanced.this, prop, text.getText());
          else
            mediator
                .notifyChange(TabAdvanced.this, propName, text.getText());
        }
      });
    }
  }

}
