// 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.
(function($, cloudStack) {
  /**
   * Serialize form data as object
   */
  var getData = function($wizard, options) {
    if (!options) options = {};

    var $forms = $wizard.find('form').filter(function() {
      return !options.all ? !$(this).closest('.multi-edit').size() : true;
    });
    var $physicalNetworkItems = $wizard.find(
      '.steps .setup-physical-network .select-container.multi'
    ).filter(':not(.disabled)');
    var $publicTrafficItems = $wizard.find(
      '.steps .setup-public-traffic .data-body .data-item');
    var $storageTrafficItems = $wizard.find(
      '.steps .setup-storage-traffic .data-body .data-item');
    var groupedForms = {};

    if ($physicalNetworkItems.find('li.traffic-type-draggable.storage').size()) {
      $wizard.find('li.conditional.storage-traffic').show();
    } else {
      $wizard.find('li.conditional.storage-traffic').hide();
    }

    if (options.all) {
      return cloudStack.serializeForm($forms, { escapeSlashes: true });
    }

    // Group form fields together, by form ID
    $forms.each(function() {
      var $form = $(this);
      var id = $form.attr('rel');

      if (!id) return true;

      groupedForms[id] = cloudStack.serializeForm($form, { escapeSlashes: true });

      return true;
    });

    // Get physical network data
    groupedForms.physicalNetworks = $.map(
      $physicalNetworkItems,
      function(network) {
        var $network = $(network);
        var $guestForm = $wizard.find('form[guest-network-id=' + $network.index() + ']');
        var trafficTypeConfiguration = {};

        $network.find('.traffic-type-draggable').each(function() {
          var $trafficType = $(this);
          var trafficTypeID = $trafficType.attr('traffic-type-id');


          trafficTypeConfiguration[trafficTypeID] = $trafficType.data('traffic-type-data');
        });

        return {
          id: $network.index(),
          name: $network.find('.field.name input[type=text]').val(),
          isolationMethod: $network.find('.field.name select').val(),

          // Traffic type list
          trafficTypes: $.map(
            $network.find('.traffic-type-draggable'),
            function(trafficType) {
              var $trafficType = $(trafficType);

              return $trafficType.attr('traffic-type-id');
            }
          ),

          // Traffic type configuration data
          trafficTypeConfiguration: trafficTypeConfiguration,

          guestConfiguration: $guestForm.size() ?
            cloudStack.serializeForm($guestForm) : null
        };
      }
    );

    // Get public traffic data (multi-edit)
    groupedForms.publicTraffic = $.map(
      $publicTrafficItems,
      function(publicTrafficItem) {
        var $publicTrafficItem = $(publicTrafficItem);
        var publicTrafficData = {};
        var fields = [
          'gateway',
          'netmask',
          'vlanid',
          'startip',
          'endip'
        ];

        $(fields).each(function() {
          publicTrafficData[this] =
            $publicTrafficItem.find('td.' + this + ' span').html();
        });

        return publicTrafficData;
      }
    );

    // Get storage traffic data (multi-edit)
    groupedForms.storageTraffic = $.map(
      $storageTrafficItems,
      function(storageTrafficItem) {
        var $storageTrafficItem = $(storageTrafficItem);
        var storageTrafficData = {};
        var fields = [
          'gateway',
          'netmask',
          'vlan',
          'startip',
          'endip'
        ];

        $(fields).each(function() {
          storageTrafficData[this] =
            $storageTrafficItem.find('td.' + this + ' span').html();
        });

        return storageTrafficData;
      }
    );

    // Hack to fix forward slash JS error
    $.each(groupedForms, function(key1, value1) {
      $.each(value1, function(key2, value2) {
        if (typeof value2 == 'string') {
          groupedForms[key1][key2] = value2.replace(/__forwardSlash__/g, '\/');
        }
      });
    });

    // Include zone network type
    if (groupedForms.zone) {
      groupedForms.zone.networkType = $forms.find('input[name=network-model]:checked').val();
      
      // Include zone isolation mode, supported for Advanced zones only
      if (groupedForms.zone.networkType == 'Advanced') {
        groupedForms.zone.sgEnabled = $forms.find('input[name=zone-advanced-sg-enabled]')
          .is(':checked') ? true : false;
      }
    }

    return groupedForms;
  };

  /**
   * Handles validation for custom UI components
   */
  var customValidation = {
    networkRanges: function($form) {
      if ($form.closest('.multi-edit').find('.data-item').size()) {
        return true;
      }

      cloudStack.dialog.notice({
        message: dictionary['message.please.add.at.lease.one.traffic.range']
      });
      return false;
    },

    physicalNetworks: function($form) {
      var $enabledPhysicalNetworks = $form.filter(':not(.disabled)').filter(function() {
        return $(this).find('.traffic-type-draggable').size();
      });
      var $trafficTypes = $enabledPhysicalNetworks.find('.traffic-type-draggable');
      var $configuredTrafficTypes = $trafficTypes.filter(function() {
        var $trafficType = $(this);

        return $trafficType.data('traffic-type-data') &&
          $trafficType.data('traffic-type-data').label.length >= 1;
      });

      if ($enabledPhysicalNetworks.size() > 1 &&
          $configuredTrafficTypes.size() != $trafficTypes.size()) {
        cloudStack.dialog.notice({
          message: _l('message.configure.all.traffic.types')
        });

        return false;
      }

      return true;
    }
  };

  /**
   * Determine if UI components in step should be custom-validated
   * (i.e., not a standard form)
   */
  var checkCustomValidation = function($step) {
    var $multiEditForm = $step.find('.multi-edit form');
    var $physicalNetworks = $step.find('.select-container.multi');
    var isCustomValidated;

    if ($multiEditForm.size()) {
      isCustomValidated = customValidation.networkRanges($multiEditForm);
    } else if ($physicalNetworks.size()) {
      isCustomValidated = customValidation.physicalNetworks($physicalNetworks);
    } else {
      isCustomValidated = true;
    }

    return isCustomValidated;
  };

  var isAdvancedNetwork = function($wizard) {
    return getData($wizard, { all: true })['network-model'] == 'Advanced';
  };

  /**
   * Setup physical network wizard UI
   */
  var physicalNetwork = {
    init: function($wizard) {
      var $existingPhysicalNetworks = physicalNetwork.getNetworks($wizard);

      // Initialize physical networks
      if (!$existingPhysicalNetworks.size()) {
        physicalNetwork.add($wizard);
      } else if (!isAdvancedNetwork($wizard)) {
        $existingPhysicalNetworks.filter(':first').siblings().each(function() {
          physicalNetwork.remove($(this));
        });
      }

      physicalNetwork.updateNetworks(physicalNetwork.getNetworks($wizard));

      $wizard.find('.traffic-types-drag-area ul li').removeClass('required disabled clone');

      // Setup clone traffic types
      $(physicalNetwork.cloneTrafficTypes($wizard)).each(function() {
        var trafficTypeID = this;

        $wizard.find('.traffic-types-drag-area ul li').filter(function() {
          return $(this).hasClass(trafficTypeID);
        }).addClass('clone');
      });

      // Setup required traffic types
      $(physicalNetwork.requiredTrafficTypes($wizard)).each(function () {
        var trafficTypeID = this;
        var $firstPhysicalNetwork = physicalNetwork.getNetworks($wizard).filter(':first');

        // First physical network gets required traffic types
        physicalNetwork.assignTrafficType(trafficTypeID, $firstPhysicalNetwork);

        $wizard.find('.traffic-types-drag-area ul li').filter(function() {
          return $(this).hasClass(trafficTypeID);
        }).addClass('required');
      });

      // Setup disabled traffic types
      $(physicalNetwork.disabledTrafficTypes($wizard)).each(function() {
        var trafficTypeID = this;
        var $trafficType = physicalNetwork.getTrafficType(this, $wizard);

        physicalNetwork.unassignTrafficType($trafficType);

        $wizard.find('.traffic-types-drag-area ul li').filter(function() {
          return $(this).hasClass(trafficTypeID);
        }).addClass('disabled');
      });
    },

    /**
     * Traffic type edit dialog
     */
    editTrafficTypeDialog: function($trafficType) {
      var trafficData = $trafficType.data('traffic-type-data') ?
            $trafficType.data('traffic-type-data') : {};
      var hypervisor = getData($trafficType.closest('.zone-wizard')).zone.hypervisor;

      cloudStack.dialog.createForm({
        form: {
          title: _l('label.edit.traffic.type'),
          desc: _l('message.edit.traffic.type'),
          fields: {
            label: { label: hypervisor + ' ' + _l('label.traffic.label'), defaultValue: trafficData.label }
          }
        },

        after: function(args) {
          $trafficType.data('traffic-type-data', args.data);
        }
      });
    },

    /**
     * Get required traffic type IDs for proper validation
     */
    requiredTrafficTypes: function($wizard) {
      return cloudStack.zoneWizard.requiredTrafficTypes({
        data: getData($wizard)
      });
    },

    /**
     * Get required traffic type IDs for proper validation
     */
    disabledTrafficTypes: function($wizard) {
      return cloudStack.zoneWizard.disabledTrafficTypes({
        data: getData($wizard)
      });
    },

    /**
     * Get clone-type traffic type IDs for proper validation
     */
    cloneTrafficTypes: function($wizard) {
      return cloudStack.zoneWizard.cloneTrafficTypes({
        data: getData($wizard)
      });
    },

    /**
     * Physical network step: Renumber network form items
     */
    renumberFormItems: function($container) {
      var $items = $container.find('.select-container.multi');

      $items.each(function() {
        var $item = $(this);
        var $networkName = $item.find('.field.name input[type=text]');
        var $networkId = $item.find('input[name=id]');
        var $networkTypes = $item.find('.field.network-types input');
        var index = $item.index();

        $networkId.val(index);
        $networkName.attr('name', 'physicalNetworks[' + index + ']' + '.name');
        $networkTypes.val(index);
      });
    },

    /**
     * Get main physical network wizard step container
     *
     * @param $elem Any elem within the container
     */
    getMainContainer: function($elem) {
      return $elem.closest('.steps .setup-physical-network');
    },

    /**
     * Returns traffic elem
     *
     * @param trafficTypeID ID of desired traffic type
     */
    getTrafficType: function(trafficTypeID, $container) {
      var $trafficType = $container.find('li.traffic-type-draggable').filter(function() {
        return $(this).attr('traffic-type-id') == trafficTypeID;
      });

      if (physicalNetwork.isTrafficTypeClone($trafficType) && !$container.closest('.select-container.multi').size()) {
        // Get traffic type from original container
        return $trafficType.filter(function() {
          return $(this).closest(
            physicalNetwork.getOriginalTrafficContainer($trafficType)
          ).size();
        });
      }

      return $trafficType;
    },

    /**
     * Get original drag container for traffic type elem
     *
     * @param $trafficType Traffic type elem
     */
    getOriginalTrafficContainer: function($trafficType) {
      var $dragContainer = physicalNetwork.getMainContainer($trafficType)
            .find('.traffic-types-drag-area ul > li')
            .filter(function() {
              return $(this).hasClass($trafficType.attr('traffic-type-id'));
            })
            .find('ul');

      return $dragContainer;
    },

    /**
     * Get all physical networks
     *
     * @param $container Physical network step - main container
     */
    getNetworks: function($container) {
      return $container.find('.select-container.multi');
    },

    /**
     * Determine if traffic type is a 'cloned' type
     *
     * @param $trafficType
     */
    isTrafficTypeClone: function($trafficType) {
      return physicalNetwork.getOriginalTrafficContainer($trafficType).parent().hasClass('clone');
    },

    /**
     * Assigns traffic type to specified physical network
     *
     * @param trafficTypeID ID of desired traffic type
     * @param $physicalNetwork Physical network elem
     */
    assignTrafficType: function(trafficTypeID, $physicalNetwork, data) {
      var $container = physicalNetwork.getMainContainer($physicalNetwork);
      var $trafficType = physicalNetwork.getTrafficType(trafficTypeID, $container);
      var $dropArea = $physicalNetwork.find('.drop-container ul');

      if ($physicalNetwork.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').size()) return false;

      if (physicalNetwork.isTrafficTypeClone($trafficType)) {
        if (!physicalNetwork.getTrafficType(trafficTypeID, $physicalNetwork).size()) {
          $trafficType = $trafficType.clone()
            .removeClass('disabled')
            .appendTo($dropArea)
            .draggable(physicalNetwork.draggableOptions($physicalNetwork.closest('.zone-wizard')));
        } else {
          return false;
        }
      } else {
        $trafficType.appendTo($dropArea);
      }

      if (data) {
        $trafficType.data('traffic-type-data', data);
      }

      physicalNetwork.updateNetworks($.merge($physicalNetwork, $physicalNetwork.siblings()));

      return $trafficType;
    },

    /**
     * Assigns traffic type to original drag container
     *
     * @param trafficTypeID ID of desired traffic type
     * @param $container Physical network wizard step container
     * @param $physicalNetwork (optional) Specific physical network to remove from -- only for clones
     */
    unassignTrafficType: function($trafficType) {
      var $wizard = $trafficType.closest('.zone-wizard');
      var $originalContainer = physicalNetwork.getOriginalTrafficContainer($trafficType);
      var $physicalNetworks = physicalNetwork.getNetworks($wizard);
      var trafficTypeID = $trafficType.attr('traffic-type-id');

      if (!physicalNetwork.isTrafficTypeClone($trafficType) &&
          $.inArray(trafficTypeID, physicalNetwork.requiredTrafficTypes($wizard)) == -1) {
        $trafficType.appendTo($originalContainer);
      } else {
        physicalNetwork.assignTrafficType(
          trafficTypeID,
          $physicalNetworks.filter(':first')
        );

        if (physicalNetwork.isTrafficTypeClone($trafficType) &&
            $physicalNetworks.find('.traffic-type-draggable[traffic-type-id=' + trafficTypeID + ']').size() > 1) {
          $trafficType.remove();
        }
      }

      return $trafficType;
    },

    /**
     * Returns true if new physical network item needs to be added
     */
    needsNewNetwork: function($containers) {
      // Basic zones do not have multiple physical networks
      if (!isAdvancedNetwork($containers.closest('.zone-wizard')))
        return false;

      var $emptyContainers = $containers.filter(function() {
        return !$(this).find('li').size();
      });

      return !$emptyContainers.size() ? $containers.size() : false;
    },

    /**
     * Cleanup physical network containers
     */
    updateNetworks: function($containers) {
      var $mainContainer = physicalNetwork.getMainContainer($containers);
      var $allPhysicalNetworks = physicalNetwork.getNetworks($mainContainer);
      var containerTotal = isAdvancedNetwork($containers.closest('.zone-wizard')) ?
            2 : 1;

      $allPhysicalNetworks.each(function() {
        var $ul = $(this).find('.drop-container ul');

        if (!$(this).find('li').size()) {
          $(this).addClass('disabled');
          $ul.fadeOut();
        } else {
          $(this).removeClass('disabled');
          $ul.show();
        }
      });

      $containers.each(function() {
        var $currentContainer = $(this);
        if (!$currentContainer.find('li').size() &&
            $containers.size() > containerTotal) {
          $currentContainer.remove();
        }
      });

      $containers = $containers.closest('.setup-physical-network')
        .find('.select-container.multi');

      if (physicalNetwork.needsNewNetwork($containers)) {
        physicalNetwork.add($mainContainer.parent());
      }

      $containers.filter(':first').find('.remove.physical-network').remove();

      return $containers;
    },

    /**
     * Default options for initializing traffic type draggables
     */
    draggableOptions: function($wizard) {
      return {
        appendTo: $wizard,
        helper: 'clone',

        // Events
        start: function(event, ui) {
          $(this).addClass('disabled');
        },

        stop: function(event, ui) {
          $(this).removeClass('disabled');
        },

        cancel: '.edit-traffic-type'
      };
    },

    /**
     * Physical network step: Generate new network element
     */
    add: function($wizard) {
      var $container = $wizard.find('.setup-physical-network .content.input-area form');
      var $physicalNetworkItem = $('<div>').addClass('select-container multi');
      var $deleteButton = $('<div>').addClass('button remove physical-network')
            .attr({ title: 'Remove this physical network' })
            .append('<span>').addClass('icon').html('&nbsp;');
      var $icon = $('<div>').addClass('physical-network-icon');
      
			var $nameField = $('<div>').addClass('field name').append(
        $('<div>').addClass('name').append(
          $('<label>').html('Physical network name')
				),
				$('<div>').addClass('value').append(
					$('<input>').attr({ type: 'text' }).addClass('required')
        )				
      );	

      
			var ovsTunnelManager = false;
			$.ajax({
				url: createURL('listConfigurations'),
				data: {
					name: 'sdn.ovs.controller'
				},
				dataType: "json",
				async: false,
				success: function(json) {					 
					var items = json.listconfigurationsresponse.configuration; //2 entries returned: 'sdn.ovs.controller', 'sdn.ovs.controller.default.label'
					$(items).each(function(){						  
						if(this.name == 'sdn.ovs.controller') {
							if(this.value == 'true' || this.value == true) {
								ovsTunnelManager = true;
							}
							return false; //break each loop
						}
					});						
				}
			});	
      //when OVS tunnel manager is used			
      //if(ovsTunnelManager == true) {    
			  //Advanced zone supports 2 isolation method(VLAN, GRE), so show dropdown including the 2 options
				if($wizard.find('.select-network-model input:radio[name=network-model]:checked').val() == 'Advanced') { 
					$nameField.append(
						$('<div>').addClass('name').append(
							$('<label>').html('Physical network name')
						),
						$('<div>').addClass('value').append(
							$('<input>').attr({ type: 'text' }).addClass('required')
						),
						$('<div>').append(
							$('<span style=\"font-size:11px\;padding-right:5px;padding-left:50px">').html('Isolation method'),
							$('<select>').append(		
								$('<option>').attr({
									value: 'VLAN'
								}).html('VLAN'),	
								$('<option>').attr({
									value: 'GRE'
                                }).html('GRE'),
                                                                $('<option>').attr({
                                                                        value: 'STT'
                                                                }).html('STT'),
                                                                $('<option>').attr({
                                                                        value: 'VNS'
                                                                }).html('VNS')

							)
						)
					);
				}
				//Basic zone supports only 1 isolation method (L3), so there is no point showing dropdown.
//            }
      //when OVS tunnel manager is not used, isolationmethods parameter in createPhysicalNetwork API is ignored. So no showing dropdown.    
      //isolationmethods parameter has not been used by network gurus so far. By default(i.e. when OVS tunnel manager is not used), networks are isolated with VLANs in Advanced zone, with L3 in basic zone.
      //No longer the case, as the Nicira stuff also depends on this now
						
			
      var $dropContainer = $('<div>').addClass('drop-container').append(
        $('<span>').addClass('empty-message').html(
          'Drag and drop traffic types you would like to add here.'
        ),
        $('<ul>').hide()
      ).droppable({
        over: function(event, ui) {
          var $ul = $(this).find('ul');

          $ul.addClass('active');

          if (!$ul.find('li').size()) {
            $(this).closest('.select-container.multi').removeClass('disabled');
            $ul.fadeIn();
          }
        },

        out: function(event, ui) {
          var $ul = $(this).find('ul');

          $ul.removeClass('active');
          physicalNetwork.updateNetworks($(this).closest('.select-container.multi'));
        },

        drop: function(event, ui) {
          var trafficTypeID = ui.draggable.attr('traffic-type-id');
          var $physicalNetwork = $(this).closest('.select-container.multi');
          var trafficTypeData = ui.draggable.data('traffic-type-data');

          if (trafficTypeID == 'guest' &&
              ui.draggable.closest('.select-container.multi').size()) {
            ui.draggable.remove();
          }

          physicalNetwork.assignTrafficType(trafficTypeID, $physicalNetwork, trafficTypeData);
        }
      });

      var $idField = $('<input>').attr({
        type: 'hidden',
        name: 'id',
        value: 0
      });

      // Initialize new default network form elem
      $physicalNetworkItem.append(
        $icon,
        $nameField,
        $idField,
        $dropContainer
      );

      // Only advanced zones can remove physical network
      if (isAdvancedNetwork($wizard)) {
        $physicalNetworkItem.prepend($deleteButton);
      }

      $physicalNetworkItem.hide().appendTo($container).fadeIn('fast');
      $physicalNetworkItem.find('.name input').val('Physical Network ' + parseInt($physicalNetworkItem.index() + 1));
      physicalNetwork.renumberFormItems($container);

      // Remove network action
      $physicalNetworkItem.find('.button.remove.physical-network').click(function() {
        physicalNetwork.remove($physicalNetworkItem);
      });

      $physicalNetworkItem.addClass('disabled'); // Since there are no traffic types yet

      return $physicalNetworkItem;
    },

    /**
     * Physical network step: Remove specified network element
     *
     * @param $physicalNetworkItem Physical network container to remove
     */
    remove: function($physicalNetworkItem) {
      var $container = $physicalNetworkItem.closest('.setup-physical-network .content.input-area form');
      var $trafficTypes = $physicalNetworkItem.find('li.traffic-type-draggable');

      $trafficTypes.each(function() {
        var trafficTypeID = $(this).attr('traffic-type-id');

        physicalNetwork.assignTrafficType(
          trafficTypeID,
          $physicalNetworkItem.prev()
        );
      });

      $trafficTypes.filter('.clone').remove();
      physicalNetwork.updateNetworks($physicalNetworkItem.parent().find('.multi'));
      $container.validate('refresh');
    }
  };

  /**
   * Configure guest traffic UI
   */
  var guestTraffic = {
    init: function($wizard, args) {
      var $physicalNetworks = physicalNetwork.getNetworks($wizard);
      var $tabs = guestTraffic.makeTabs($physicalNetworks, args);
      var $container = guestTraffic.getMainContainer($wizard);
      var $expand = $('<div title="Add multiple VLAN Ranges">').addClass('expand').append(
        $('<span>').addClass('icon').html('&nbsp;'),
        $('<span>Add VLAN range</span>')
      );
      var $hide = $('<div title="Hide VLAN Range">').addClass('hide');
      var $hidelabel = $('<div>').addClass('hide-label').html('Hide VLAN Range');
      var data = getData($wizard, { all: true });
      var $vlanRanges, $vlanRangeFirst, $subnav;

      // Cleanup
      guestTraffic.remove($wizard);

      $container.find('.content form').hide();
      $tabs.appendTo($container.find('.content .select-container'));
      $subnav = $container.find('ul.subnav').remove(); // Fix to avoid subnav becoming tab ul
      $container.tabs();
      $container.prepend($subnav);
      $container.find('.field').hide();
      $container.find('[rel=vlanRange]').show();
      $vlanRanges = $container.find('.field[rel=vlanRange]:visible');
      $vlanRangeFirst = $vlanRanges.filter(':first');

      //
      // Multiple Vlan Ranges functionality
      //
      var addVlan = function(options) {
        var evenOdd = function() {
          cloudStack.evenOdd($container, '.field[rel=vlanRange]:visible', {
            even: function($elem) { $elem.addClass('even') },
            odd: function($elem) { $elem.addClass('odd') }
          });
        };

        var $vlanClone = $vlanRangeFirst.clone()
          .insertAfter($container.find('.field[rel=vlanRange]:visible').filter(':last'));
        var $remove = $hide.clone()
          .appendTo($vlanClone);

        if (options) {
          if (options.start)
            $vlanClone.find('inpunt:first').val(options.start);

          if (options.end)
            $vlanClone.find('input:last').val(options.end);
        }

        $remove.click(function() {
          $vlanClone.remove();
          evenOdd();
        });

        evenOdd();
      };

      $expand.insertAfter($container.find('form [rel=vlanRange]')).click(function() {
        addVlan();
      });

      if (data.vlanRangeStart || data.vlanRangeEnd) {
        if (($.isArray(data.vlanRangeStart) || $.isArray(data.vlanRangeEnd)) &&
            (data.vlanRangeStart.length > 1 || data.vlanRangeEnd.length > 1)) {
          $(data.vlanRangeStart).map(function(index) {
            if (index) {
              addVlan({
                start: data.vlanRangeStart[index],
                end: data.vlanRangeEnd[index]
              });
            }
          });

          $vlanRangeFirst.find('input:first').val(data.vlanRangeStart[0]);
          $vlanRangeFirst.find('input:last').val(data.vlanRangeEnd[0]);
        } else { // Only 1 vlan range
          $vlanRangeFirst.find('input:first').val(data.vlanRangeStart);
          $vlanRangeFirst.find('input:last').val(data.vlanRangeEnd);
        }
      }
    },

    /**
     * Cleanup
     */
    remove: function($wizard) {
      var $container = guestTraffic.getMainContainer($wizard);

      // Cleanup
      $container.tabs('destroy');
      $container.find('.physical-network-item').remove();
      $container.find('.content form').show();
    },

    getMainContainer: function($wizard) {
      return $wizard.find('.steps .setup-guest-traffic');
    },

    makeTabs: function($physicalNetworks, args) {
      var $tabs = $('<ul></ul>').addClass('physical-network-item');
      var $content = $();

      // Only use networks w/ guest traffic type
      $physicalNetworks = $physicalNetworks.filter(function() {
        return $(this).find('li.guest').size();

        return true;
      });

      $physicalNetworks.each(function() {
        var $network = $(this);
        var $form = makeForm(args, 'guestTraffic', {});
        var refID = $network.find('input[name=id]').val();
        var networkID = 'physical-network-' + refID;

        $form.attr('guest-network-id', refID);

        $tabs.append($('<li></li>').append(
          $('<a></a>')
            .attr({ href: '#' + networkID })
            .html($network.find('.field.name input').val())
        ));
        $.merge(
          $content,
          $('<div></div>')
            .addClass('physical-network-item')
            .attr({ id: networkID })
            .append($form)
        );

        $form.validate();
      });

      $tabs.find('li:first').addClass('first');
      $tabs.find('li:last').addClass('last');

      return $.merge($tabs, $content);
    }
  };

  /**
   * Generate dynamic form, based on ID of form object given
   */
  var makeForm = function(args, id, formState) {
    var form = cloudStack.dialog.createForm({
      noDialog: true,
      context: $.extend(true, {}, cloudStack.context, {
        zones: [formState]
      }),
      form: {
        title: '',
        desc: '',
        fields: args.forms[id].fields
      },
      after: function(args) {}
    });

    var $form = form.$formContainer.find('form');

    // Cleanup form to follow zone wizard CSS naming
    $form.attr('rel', id);
    $form.find('input[type=submit]').remove();
    $form.find('.form-item').addClass('field').removeClass('form-item');
    $form.find('label.error').hide();
    $form.find('.form-item .name').each(function() {
      $(this).html($(this).find('label'));
    });
    $form.find('label[for]').each(function() {
      var forAttr = $(this).attr('for');
      $form.find('#' + forAttr).attr('id', id + '_' + forAttr);
      $(this).attr('for', id + '_' + forAttr)
    });

    $form.find('select, input').change(function() {
      cloudStack.evenOdd($form, '.field:visible', {
        even: function($row) {
          $row.removeClass('odd');
        },
        odd: function($row) {
          $row.addClass('odd');
        }
      });
    });

    return $form;
  };

  cloudStack.uiCustom.zoneWizard = function(args) {
    return function() {
      var $wizard = $('#template').find('div.zone-wizard').clone();
      var $progress = $wizard.find('div.progress ul li');
      var $steps = $wizard.find('div.steps').children().hide().filter(':not(.disabled)');

      $wizard.data('startfn', null);

      // Close wizard
      var close = function() {
        $wizard.dialog('destroy');
        $('div.overlay').fadeOut(function() { $('div.overlay').remove(); });
      };

      // Save and close wizard
      var completeAction = function() {
        var $launchStep = $wizard.find('.steps .review');
        var data = getData($wizard);
        var enableZoneAction = args.enableZoneAction;

        // Convert last step to launch appearance
        $launchStep.find('.main-desc').hide();
        $launchStep.find('.main-desc.launch').show();
        $launchStep.find('.launch-container').show();
        $launchStep.find('ul').html('');
        $wizard.find('.buttons').hide();
        $wizard.find('.button.previous').remove();

        var makeMessage = function(message, isError) {
          var $li = $('<li>')
                .addClass(!isError ? 'loading' : 'info')
                .append(
                  $('<span>').addClass('icon').html('&nbsp;'),
                  $('<span>').addClass('text').html(message)
                );
          var $launchContainer = $launchStep.find('.launch-container');

          $launchStep.find('ul').append($li);
          $li.prev().removeClass('loading');
          $launchContainer.scrollTop($launchContainer.height());

          if (isError) {
            $li.prev().addClass('error');
          }

        };

        args.action({
          data: data,
          startFn: $wizard.data('startfn'),
          uiSteps: $.map(
            $wizard.find('.steps > div'),
            function(step) {
              return $(step).attr('zone-wizard-step-id');
            }
          ),
          response: {
            success: function(args) {
              $launchStep.find('ul li').removeClass('loading');

              var closeWindow = function() {
                close();
                $(window).trigger('cloudStack.fullRefresh');
              };

              var enableZone = function() {
                makeMessage(dictionary['message.enabling.zone']);

                enableZoneAction({
                  formData: data,
                  data: data,
                  launchData: args.data,
                  response: {
                    success: function(args) {
                      closeWindow();
                    },

                    error: function(message) {
                      cloudStack.dialog.notice({ message: dictionary['error.could.not.enable.zone'] + ':</br>' + message });
                    }
                  }
                });
              };

              cloudStack.dialog.confirm({
                message: dictionary['message.zone.creation.complete.would.you.like.to.enable.this.zone'],
                action: function() {
                  enableZone();
                },
                cancelAction: function() {
                  closeWindow();
                }
              });
            },
            error: function(stepID, message, start) {
              var goNextOverride = function(event) {
                $(this).unbind('click', goNextOverride);
                showStep(stepID, false, { nextStep: 'launch' });

                return false;
              };

              $wizard.find('.buttons').show();
              $wizard.find('.buttons .button.next')
                .removeClass('final')
                .html('<span>Fix errors</span>')
                .click(goNextOverride);
              makeMessage(dictionary['error.something.went.wrong.please.correct.the.following'] + ':<br/>' + message, true);
              $wizard.data('startfn', start);
            },
            message: makeMessage
          }
        });
      };

      // Go to specified step in wizard,
      // updating nav items and diagram
      var showStep = function(index, goBack, options) {
        if (!options) options = {};

        if (typeof index == 'string') {
          index = $wizard.find('[zone-wizard-step-id=' + index + ']').index() + 1;
        }

        var targetIndex = index - 1;

        if (index <= 1) targetIndex = 0;
        if (targetIndex == $steps.size()) {
          completeAction();
        }

        $steps.hide();
        $wizard.find('.buttons').show();

        var $targetStep = $($steps[targetIndex]).show();
        var $uiCustom = $targetStep.find('[ui-custom]');
        var formState = getData($wizard, { all: true });
        var groupedFormState = getData($wizard);
        var formID = $targetStep.attr('zone-wizard-form');
        var stepPreFilter = cloudStack.zoneWizard.preFilters[
          $targetStep.attr('zone-wizard-prefilter')
        ];

        // Bypass step check
        if (stepPreFilter && !stepPreFilter({ data: formState, groupedData: groupedFormState })) {
          return showStep(
            !goBack ? index + 1 : index - 1,
            goBack
          );
        }

        if (formID) {
          if (!$targetStep.find('form').size()) {
            makeForm(args, formID, formState).appendTo($targetStep.find('.content.input-area .select-container'));

            setTimeout(function() {
              cloudStack.evenOdd($targetStep, '.field:visible', {
                even: function() {},
                odd: function($row) {
                  $row.addClass('odd');
                }
              });
            }, 50);
          } else {
            // Always re-activate selects
            $targetStep.find('form select').each(function() {
              var $select = $(this);
              var selectFn = $select.data('dialog-select-fn');
              var originalVal = $select.val();

              if (selectFn) {
                $select.html('');
                selectFn({
                  context: {
                    zones: [formState]
                  }
                });
                $select.val(originalVal);
                $select.trigger('change');
              }
            });
          }

          if (args.forms[formID].preFilter) {
            var preFilter = args.forms[formID].preFilter({
              $form: $targetStep.find('form'),
              data: formState
            });
          }
        }

        // Custom UI manipulations for specific steps
        switch($targetStep.attr('zone-wizard-step-id')) {
        case 'configureGuestTraffic':
				  if (formState['network-model'] == 'Advanced' && formState['zone-advanced-sg-enabled']	== undefined) {
            guestTraffic.init($wizard, args); //initialize multiple tabs (tabs is as many as Guest Traffic types in multiple physical networks in Advanced Zone without SG)
          } else {
            guestTraffic.remove($wizard);
          }
          break;

        case 'setupPhysicalNetwork':
          physicalNetwork.init($wizard);
        }

        if ($uiCustom.size()) {
          $uiCustom.each(function() {
            var $item = $(this);
            var id = $item.attr('ui-custom');

            $item.replaceWith(
              args.customUI[id]({
                data: formState,
                context: cloudStack.context
              })
            )
          });
        }

        if (!targetIndex) {
          $wizard.find('.button.previous').hide();
        } else {
          $wizard.find('.button.previous').show();
        }

        var $nextButton = $wizard.find('.button.next');
        $nextButton.find('span').html('Next');
        $nextButton.removeClass('final post-launch');

        // Show launch button if last step
        if ($targetStep.index() == $steps.size() - 1 || options.nextStep) {
          $nextButton.find('span').html(options.nextStep ? 'Save changes' : 'Launch zone');
          $nextButton.addClass('final');

          if (options.nextStep) { $nextButton.addClass('post-launch'); }
        }

        // Update progress bar
        var $targetProgress = $progress.removeClass('active').filter(function() {
          return $(this).index() <= targetIndex;
        }).toggleClass('active');

        setTimeout(function() {
          if (!$targetStep.find('input[type=radio]:checked').size()) {
            $targetStep.find('input[type=radio]:first').click();
          }
        }, 50);

        $targetStep.find('form').validate();
      };

      // Events
      $wizard.find('select').change(function(event) {
        // Conditional selects (on step 4 mainly)
        var $target = $(this);
        var $tagged = $wizard.find('.conditional.vlan-type-tagged');
        var $untagged = $wizard.find('.conditional.vlan-type-untagged');
        var $accountSpecific = $wizard.find('.field.conditional.ip-scope-account-specific');

        // VLAN - tagged
        if ($target.is('[name=vlan-type]')) {
          $tagged.hide();
          $untagged.hide();
          $accountSpecific.hide();

          if ($target.val() == 'tagged') {
            $untagged.hide();
            $tagged.show();
          }
          else if ($target.val() == 'untagged') {
            $tagged.hide();
            $untagged.show();
          }

          $.merge($tagged, $untagged).find('select:visible').trigger('change');

          cloudStack.evenOdd($wizard, '.field:visible', {
            even: function($elem) { $elem.removeClass('odd'); $elem.addClass('even'); },
            odd: function($elem) { $elem.removeClass('even'); $elem.addClass('odd'); }
          });

          return true;
        }

        // IP Scope - acct. specific
        if ($target.is('select.ip-scope')) {
          $accountSpecific.hide();
          if ($target.val() == 'account-specific') $accountSpecific.show();

          cloudStack.evenOdd($wizard, '.field:visible', {
            even: function($elem) { $elem.removeClass('odd'); $elem.addClass('even'); },
            odd: function($elem) { $elem.removeClass('even'); $elem.addClass('odd'); }
          });
        }

        return true;
      });

      $wizard.click(function(event) {
        var $target = $(event.target);

        // Radio button
        if ($target.is('[type=radio]')) {

          if ($target.attr('name') == 'network-model') {
            var $inputs = $wizard.find('.isolation-mode').find('input[name=isolation-mode]').attr({
              disabled: 'disabled'
            });

            var $selectArea = $target.closest('.select-area');

            if ($target.val() == 'Advanced') {
              $inputs.attr('disabled', false);
              $selectArea.removeClass('disabled')
                .find('.isolation-mode input').attr('disabled', false);
            } else if ($target.val() == 'Basic') {
              $selectArea.siblings('.advanced-zone').addClass('disabled')
                .find('.isolation-mode input').attr('disabled', 'disabled');
            }
          }

          return true;
        }

        // Checkbox
        if ($target.is('[type=checkbox]:checked')) {
          $('div.conditional.' + $target.attr('name')).hide();

          return true;
        } else if ($target.is('[type=checkbox]:unchecked')) {
          $('div.conditional.' + $target.attr('name')).show();

          return true;
        }

        // Next button
        if ($target.closest('div.button.next').size()) {
          var $step = $steps.filter(':visible');
          // Validation
          var $form = $('form:visible').filter(function() {
            // Don't include multi-edit (validation happens separately)
            return !$(this).closest('.multi-edit').size();
          });

          // Handle validation for custom UI components
          var isCustomValidated = checkCustomValidation($step);
          if (($form.size() && !$form.valid()) || !isCustomValidated) {
            if (($form && $form.find('.error:visible').size()) || !isCustomValidated)
              return false;
          }

          if (!$target.closest('.button.next.final').size())
            showStep($steps.filter(':visible').index() + 2);
          else {
            if ($target.closest('.button.next.final.post-launch').size()) {
              showStep('launch');
            }

            completeAction();
          }

          return false;
        }

        // Previous button
        if ($target.closest('div.button.previous').size()) {
          showStep($steps.filter(':visible').index(), true);

          return false;
        }

        // Close button
        if ($target.closest('div.button.cancel').size()) {
          close();

          return false;
        }

        // Edit link
        if ($target.closest('div.edit').size()) {
          var $edit = $target.closest('div.edit');

          showStep($edit.find('a').attr('href'));

          return false;
        }

        // Edit traffic type button
        var $editTrafficTypeButton = $target.closest('.drop-container .traffic-type-draggable .edit-traffic-type');
        var $trafficType = $editTrafficTypeButton.closest('.traffic-type-draggable');

        if ($editTrafficTypeButton.size()) {
          physicalNetwork.editTrafficTypeDialog($trafficType);

          return false;
        }

        return true;
      });

      // Add/remove network action
      $wizard.find('.button.add.new-physical-network').click(function() {
        addPhysicalNetwork($wizard);
      });

      // Traffic type draggables
      $wizard.find('.traffic-type-draggable').draggable(physicalNetwork.draggableOptions($wizard));

      // For removing traffic types from physical network
      $wizard.find('.traffic-types-drag-area').droppable({
        drop: function(event, ui) {
          physicalNetwork.unassignTrafficType(ui.draggable);

          return true;
        }
      });

      showStep(1);

      return $wizard.dialog({
        title: 'Add zone',
        closeOnEscape: false,
        width: 750,
        height: 665,
        zIndex: 5000,
        resizable: false
      }).closest('.ui-dialog').overlay();
    };
  };
})(jQuery, cloudStack);
