').addClass('icon'))
        );
      }
    };
    var $diagramParts = elems.diagramParts();
    var showDiagram = function(parts) {
      $diagramParts.children().hide();
      $diagramParts.find(parts).show();
    };
    /**
     * Show tooltip for focused form elements
     */
    var showTooltip = function($formContainer, sectionID) {
      var $tooltip = elems.tooltip(_l('label.hints'), '');
      $formContainer.find('input[type=text]').focus(function() {
        var $input = $(this);
        $tooltip.find('p').html('');
        $tooltip.appendTo($formContainer);
        $tooltip.css({
          top: $(this).position().top - 20
        });
        var content = getCopy(
          'tooltip.' + sectionID + '.' + $input.attr('name'),
          $tooltip.find('p')
        );
      });
      $formContainer.find('input').blur(function() {
        $tooltip.remove();
      });
    };
    /**
     * Layout/behavior for each step in wizard
     */
    var steps = {
      eula: function(args) {
        var $intro = $('
').addClass('intro eula');
        var $title = $('
').addClass('title').html(_l('label.license.agreement'));
        var $subtitle = $('
').addClass('subtitle').html(_l('label.license.agreement.subtitle'));
        var $copy = $('
').addClass('eula-copy').html(eulaHTML);
        var $continue = elems.nextButton(_l('label.agree'));
        $continue.click(function() {
          goTo('intro');
          return false;
        });
        
        return $intro.append($title, $subtitle,
                             $copy,
                             $continue);
      },
      
      intro: function(args) {
        var $intro = $('
').addClass('intro what-is-cloudstack');
        var $title = $('
').addClass('title').html(_l('label.what.is.cloudstack'));
        var $subtitle = $('
').addClass('subtitle').html(_l('label.introduction.to.cloudstack'));
        var $copy = getCopy('whatIsCloudStack', $('
'));
        var $continue = elems.nextButton(_l('label.continue.basic.install'));
        var $advanced = elems.nextButton(_l('label.skip.guide')).addClass('advanced-installation');
        $continue.click(function() {
          goTo('changeUser');
          return false;
        });
        $advanced.click(function() {
          complete();
          return false;
        });
        return $intro.append($title, $subtitle,
                             $copy,
                             $advanced,
                             $continue);
      },
      changeUser: function(args) {
        var $changeUser = $('
').addClass('step change-user');
        var $form = $('
').appendTo($changeUser);
        // Fields
        var $password = $('
').addClass('required').attr({
          id: 'password',
          type: 'password',
          name: 'password'
        });
        var $passwordConfirm = $('
').addClass('required').attr({
          id: 'password-confirm',
          type: 'password',
          name: 'password-confirm'
        });
        var $save = elems.nextButton(_l('label.save.and.continue'), { type: 'submit' });
        $form.append(
          $('
').addClass('title').html(_l('message.change.password')),
          $('
').addClass('field').append(
            $('
' + _l('label.new.password') + ': '), $password
          ),
          $('
').addClass('field').append(
            $('
' + _l('label.confirm.password') + ': '), $passwordConfirm
          ),
          $save
        );
        $form.validate({
          rules: {
            'password-confirm': {
              equalTo: '#password'
            }
          },
          messages: {
            'password-confirm': {
              equalTo: _l('error.password.not.match')
            }
          }
        });
        // Save event
        $form.submit(function() {
          if (!$form.valid()) return false;
          var $loading = $('
').addClass('loading-overlay').prependTo($form);
          cloudStack.installWizard.changeUser({
            data: cloudStack.serializeForm($form),
            response: {
              success: function(args) {
                goTo('addZoneIntro', 'newUser', $form);
              }
            }
          });
          return false;
        });
        return $changeUser;
      },
      /**
       * Add zone intro text
       * @param args
       */
      addZoneIntro: elems.stepIntro({
        title: _l('label.installWizard.addZoneIntro.title'),
        subtitle: _l('label.installWizard.addZoneIntro.subtitle'),
        copyID: 'whatIsAZone',
        prevStepID: 'changeUser',
        nextStepID: 'addZone',
        diagram: '.part.zone'
      }),
      /**
       * Add zone form
       */
      addZone: elems.step({
        title: _l('label.installWizard.addZone.title'),
        id: 'add-zone',
        stateID: 'zone',
        tooltipID: 'addZone',
        diagram: '.part.zone',
        prevStepID: 'addZoneIntro',
        nextStepID: 'addPodIntro',
        form: {
          name: { label: 'label.name', validation: { required: true } },
          dns1: { label: 'label.dns.1', validation: { required: true } },
          dns2: { label: 'label.dns.2' },
          internaldns1: { label: 'label.internal.dns.1', validation: { required: true } },
          internaldns2: { label: 'label.internal.dns.2' }
        }
      }),
      /**
       * Add pod intro text
       * @param args
       */
      addPodIntro: elems.stepIntro({
        title: _l('label.installWizard.addPodIntro.title'),
        subtitle: _l('label.installWizard.addPodIntro.subtitle'),
        copyID: 'whatIsAPod',
        prevStepID: 'addZone',
        nextStepID: 'addPod',
        diagram: '.part.zone, .part.pod'
      }),
      /**
       * Add pod form
       * @param args
       */
      addPod: elems.step({
        title: _l('label.add.pod'),
        id: 'add-pod',
        stateID: 'pod',
        tooltipID: 'addPod',
        diagram: '.part.zone, .part.pod',
        prevStepID: 'addPodIntro',
        nextStepID: 'configureGuestTraffic',
        form: {
          name: { label: 'label.name', validation: { required: true }},
          reservedSystemGateway: { label: 'label.gateway', validation: { required: true }},
          reservedSystemNetmask: { label: 'label.netmask', validation: { required: true }},
          ipRange: {
            label: 'label.ip.range',
            range: ['reservedSystemStartIp', 'reservedSystemEndIp'],
            validation: { required: true }
          }
        }
      }),
      /**
       * Add guest network form
       */
      configureGuestTraffic: elems.step({
        title: _l('label.add.guest.network'),
        id: 'add-guest-network',
        stateID: 'guestTraffic',
        tooltipID: 'configureGuestTraffic',
        diagram: '.part.zone, .part.pod',
        prevStepID: 'addPod',
        nextStepID: 'addClusterIntro',
        form: {
          guestGateway: { label: 'label.gateway', validation: { required: true } },
          guestNetmask: { label: 'label.netmask', validation: { required: true } },
          guestIPRange: { label: 'label.ip.range', range: ['guestStartIp', 'guestEndIp'], validation: { required: true } }
        }
      }),
      /**
       * Add cluster intro text
       * @param args
       */
      addClusterIntro: elems.stepIntro({
        title: _l('label.installWizard.addClusterIntro.title'),
        subtitle: _l('label.installWizard.addClusterIntro.subtitle'),
        copyID: 'whatIsACluster',
        prevStepID: 'configureGuestTraffic',
        nextStepID: 'addCluster',
        diagram: '.part.zone, .part.cluster'
      }),
      /**
       * Add cluster form
       * @param args
       */
      addCluster: elems.step({
        title: _l('label.add.cluster'),
        id: 'add-cluster',
        stateID: 'cluster',
        tooltipID: 'addCluster',
        prevStepID: 'addClusterIntro',
        nextStepID: 'addHostIntro',
        diagram: '.part.zone, .part.cluster',
        form: {
          hypervisor: {
            label: 'label.hypervisor',
            select: function(args) {
              args.response.success({ data: [
                { id: 'XenServer', description: 'XenServer' },
								{ id: 'KVM', description: 'KVM'}
              ]});
            }
          },
          name: { label: 'label.name', validation: { required: true }}
        }
      }),
      /**
       * Add host intro text
       * @param args
       */
      addHostIntro: elems.stepIntro({
        title: _l('label.installWizard.addHostIntro.title'),
        subtitle: _l('label.installWizard.addHostIntro.subtitle'),
        copyID: 'whatIsAHost',
        prevStepID: 'addCluster',
        nextStepID: 'addHost',
        diagram: '.part.zone, .part.host'
      }),
      /**
       * Add host form
       * @param args
       */
      addHost: elems.step({
        title: _l('label.add.host'),
        id: 'add-host',
        stateID: 'host',
        tooltipID: 'addHost',
        prevStepID: 'addHostIntro',
        nextStepID: 'addPrimaryStorageIntro',
        diagram: '.part.zone, .part.host',
        form: {
          hostname: {
            label: 'label.host.name',
            validation: { required: true }
          },
          username: {
            label: 'label.username',
            validation: { required: true }
          },
          password: {
            label: 'label.password',
            validation: { required: true },
            isPassword: true
          }
        }
      }),
      /**
       * Add primary storage intro text
       * @param args
       */
      addPrimaryStorageIntro: elems.stepIntro({
        title: _l('label.installWizard.addPrimaryStorageIntro.title'),
        subtitle: _l('label.installWizard.addPrimaryStorageIntro.subtitle'),
        copyID: 'whatIsPrimaryStorage',
        prevStepID: 'addHost',
        nextStepID: 'addPrimaryStorage',
        diagram: '.part.zone, .part.primaryStorage'
      }),
      /**
       * Add primary storage
       * @param args
       */
      addPrimaryStorage: elems.step({
        title: _l('label.add.primary.storage'),
        id: 'add-primary-storage',
        stateID: 'primaryStorage',
        tooltipID: 'addPrimaryStorage',
        prevStepID: 'addPrimaryStorageIntro',
        nextStepID: 'addSecondaryStorageIntro',
        diagram: '.part.zone, .part.primaryStorage',
        form: {
          name: {
            label: 'label.name',
            validation: { required: true }
          },
          protocol: {
            label: 'label.protocol',
            select: function(args) {
              args.response.success({
                data: { id: 'nfs', description: 'NFS' }
              });
            }
          },
          server: {
            label: 'label.server',
            validation: { required: true }
          },
          path: {
            label: 'label.path',
            validation: { required: true }
          }
        }
      }),
      /**
       * Add secondary storage intro text
       * @param args
       */
      addSecondaryStorageIntro: elems.stepIntro({
        title: _l('label.installWizard.addSecondaryStorageIntro.title'),
        subtitle: _l('label.installWizard.addSecondaryStorageIntro.subtitle'),
        copyID: 'whatIsSecondaryStorage',
        prevStepID: 'addPrimaryStorage',
        nextStepID: 'addSecondaryStorage',
        diagram: '.part.zone, .part.secondaryStorage'
      }),
      /**
       * Add secondary storage
       * @param args
       */
      addSecondaryStorage: elems.step({
        title: _l('label.add.secondary.storage'),
        id: 'add-secondary-storage',
        stateID: 'secondaryStorage',
        tooltipID: 'addSecondaryStorage',
        prevStepID: 'addSecondaryStorageIntro',
        nextStepID: 'launchInfo',
        diagram: '.part.zone, .part.secondaryStorage',
        form: {
          nfsServer: {
            label: 'label.nfs.server',
            validation: { required: true }
          },
          path: {
            label: 'label.path',
            validation: { required: true }
          }
        }
      }),
      /**
       * Pre-launch text
       */
      launchInfo: function(args) {
        var $intro = $('
').addClass('intro');
        var $title = $('
').addClass('title')
          .html(_l('label.congratulations'));
        var $subtitle = $('
').addClass('subtitle')
          .html(_l('label.installWizard.click.launch'));
        var $continue = elems.nextButton(_l('label.launch'));
        var $prev = elems.prevButton(_l('label.back'));
        $continue.click(function() {
          goTo('launch');
          return false;
        });
        $prev.click(function() {
          goTo('addSecondaryStorage');
        });
        showDiagram('.part.zone, .part.secondaryStorage');
        return $intro.append(
          $title, $subtitle,
          $prev, $continue
        );
      },
      /**
       * Pre-launch test -- after error correction
       */
      launchInfoError: function(args) {
        var $intro = $('
').addClass('intro');
        var $title = $('
').addClass('title')
              .html(_l('label.corrections.saved'));
        var $subtitle = $('
').addClass('subtitle')
              .html(_l('message.installWizard.click.retry'));
        var $continue = elems.nextButton(_l('label.launch'));
        $continue.click(function() {
          goTo('launch');
          return false;
        });
        showDiagram('.part.zone, .part.secondaryStorage');
        return $intro.append(
          $title, $subtitle,
          $continue
        );
      },
      /**
       * Initiates launch tasks
       */
      launch: function(args) {
        var $intro = $('
').addClass('intro');
        var $title = $('
').addClass('title')
              .html(_l('message.installWizard.now.building'));
        var $subtitle = $('
').addClass('subtitle');
        showDiagram('.part.loading');
        $intro.append(
          $title, $subtitle
        );
        cloudStack.installWizard.action({
          data: state,
          startFn: launchStart,
          response: {
            message: function(msg) {
              var $li = $('
').html(_l(msg));
              $subtitle.append($li);
              $li.siblings().addClass('complete');
            },
            success: function() {
              goTo('complete');
            },
            error: function(stepID, message, callback) {
              launchStart = callback;
              $subtitle.find('li:last').addClass('error');
              $subtitle.append(
                $('').html(
                  _l('error.installWizard.message') + ':
').addClass('button').append(
                  $('
').html(_l('label.back'))
                ).click(function() {
                  goTo(stepID, null, null, {
                    nextStep: 'launchInfoError'
                  });
                })
              );
            }
          }
        });
        return $intro;
      },
      complete: function(args) {
        var $intro = $('
').addClass('intro');
        var $title = $('
').addClass('title')
              .html(_l('message.setup.successful'));
        var $subtitle = $('
').addClass('subtitle')
              .html(_l('label.may.continue'));
        var $continue = elems.nextButton(_l('label.launch'));
        showDiagram('');
        $continue.click(function() {
          $installWizard.fadeOut(function() {
            complete();
          });
        });
        return $intro.append(
          $title, $subtitle, $continue
        );
      }
    };
    var initialStep = eulaHTML ?
          steps.eula().addClass('step') : steps.intro().addClass('step');
    showDiagram('');
    $('html body').addClass('install-wizard');
    $installWizard.append(
      elems.header(),
      elems.body().append(initialStep),
      $diagramParts
    ).appendTo($container);
  };
  cloudStack.uiCustom.installWizard = installWizard;
}(jQuery, cloudStack));