// 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, $) {
  var pageElems = cloudStack.uiCustom.projectsTabs = {
    /**
     * User management multi-edit
     */
    userManagement: function(args) {
      var multiEdit = !args.useInvites ?
            cloudStack.projects.addUserForm :
            cloudStack.projects.inviteForm;

      var $multi = $('<div>').multiEdit($.extend(true, {}, multiEdit, {
        context: args.context
      }));

      if (args.useInvites) {
        var $fields = $multi.find('form table').find('th, td');
        var $accountFields = $fields.filter(function() {
          return $(this).hasClass('account');
        });
        var $emailFields = $fields.filter(function() {
          return $(this).hasClass('email');
        });

        $multi.prepend(
          $('<div>').addClass('add-by')
            .append($('<span>').html(_l('label.add.by') + ':'))
            .append(
              $('<div>').addClass('selection')
                .append(
                  $('<input>').attr({
                    type: 'radio',
                    name: 'add-by',
                    checked: 'checked'
                  }).click(function() {
                    $accountFields.show();
                    $emailFields.hide();
                    $emailFields.find('input').val('');

                    return true;
                  }).click()
                )
                .append($('<label>').html(_l('label.account')))
                .append(
                  $('<input>').attr({
                    type: 'radio',
                    name: 'add-by'
                  }).click(function() {
                    $accountFields.hide();
                    $accountFields.find('input').val('');
                    $emailFields.show();

                    return true;
                  })
                )
                .append($('<label>').html(_l('label.email')))
            )
        );
      }

      return $multi;
    },

    dashboardTabs: {
      overview: function() {
        var $dashboard = $('#template').find('.project-dashboard-view').clone();
        $dashboard.data('tab-title', _l('label.menu.dashboard'));

        var getData = function() {
          // Populate data
          $dashboard.find('[data-item]').hide();
          var $loading = $('<div>').addClass('loading-overlay').prependTo($dashboard);
          cloudStack.projects.dashboard({
            response: {
              success: function(args) {
                $loading.remove();
                var data = args.data;

                // Iterate over data; populate corresponding DOM elements
                $.each(data, function(key, value) {
                  var $elem = $dashboard.find('[data-item=' + key + ']');

                  // This assumes an array of data
                  if ($elem.is('ul')) {
                    $elem.show();
                    var $liTmpl = $elem.find('li').remove();
                    $(value).each(function() {
                      var item = this;
                      var $li = $liTmpl.clone().appendTo($elem).hide();

                      $.each(item, function(arrayKey, arrayValue) {
                        var $arrayElem = $li.find('[data-list-item=' + arrayKey + ']');

                        $arrayElem.html(_s(arrayValue));
                      });

                      $li.attr({ title: item.description });

                      $li.fadeIn();
                    });
                  } else {
                    $elem.each(function() {
                      var $item = $(this);
                      if ($item.hasClass('chart-line')) {
                        $item.show().animate({ width: value + '%' });
                      } else {
                        $item.hide().html(_s(value)).fadeIn();
                      }
                    });
                  }
                });
              }
            }
          });
        };

        getData();

        $dashboard.find('.button.manage-resources').click(function() {
          $('.navigation-item.network').click();
        });

        $dashboard.find('.info-box.events .button').click(function() {
          $('.navigation-item.events').click();
        });

        return $dashboard;
      },

      users: function() {
        return $('<div>').addClass('management').data('tab-title', _l('label.menu.accounts'));
      },

      invitations: function() {
        return $('<div>').addClass('management-invite').data('tab-title', _l('label.invitations'));
      },

      resources: function(options) {
        if (!options) options = {};

        var $resources = $('<div>').addClass('resources').data('tab-title', _l('label.resources'));
        var $form = $('<form>');
        var $submit = $('<input>').attr({
          type: 'submit'
        }).val(_l('label.apply'));

        cloudStack.projects.resourceManagement.dataProvider({
          response: {
            success: function(args) {
              $(args.data).each(function() {
                var resource = this;
                var $field = $('<div>').addClass('field');
                var $label = $('<label>').attr({
                  'for': resource.type
                }).html(_s(resource.label));
                var $input = $('<input>').attr({
                  type: 'text',
                  name: resource.type,
                  value: resource.value,
                  id: resource.type
                }).addClass('required');

                $field.append($label, $input);
                $field.appendTo($form);
              });

              $form.validate();
              $form.submit(function() {
                if (!$form.valid) {
                  return false;
                }

                var $loading = $('<div>').addClass('loading-overlay').appendTo($form);

                cloudStack.projects.resourceManagement.update({
                  data: cloudStack.serializeForm($form),
                  response: {
                    success: function(args) {
                      $loading.remove();
                      $('.notifications').notifications('add', {
                        section: 'dashboard',
                        desc: 'label.update.project.resources',
                        interval: 1000,
                        poll: function(args) {
                          args.complete();
                        }
                      });
                    }
                  }
                }, options.projectID);

                return false;
              });

              $submit.appendTo($form);
              $form.appendTo($resources);
            }
          }
        }, options.projectID);

        return $resources;
      }
    },

    /**
     * Projects dashboard
     */
    dashboard: function() {
      var tabs = {
        dashboard: pageElems.dashboardTabs.overview
      };

      // Only show management tabs to owner of project
      if (isAdmin() || isDomainAdmin() || (
        cloudStack.context.projects &&
          (cloudStack.context.projects[0].account == cloudStack.context.users[0].account)
      )) {
        tabs.users = pageElems.dashboardTabs.users;

        if (g_capabilities.projectinviterequired) {
          tabs.invitations = pageElems.dashboardTabs.invitations;
        }

        if (isAdmin() || isDomainAdmin()) {
          tabs.resources = pageElems.dashboardTabs.resources;
        }
      }

      var $tabs = $('<div>').addClass('tab-content').append($('<ul>'));
      var $toolbar = $('<div>').addClass('toolbar');

      // Make UI tabs
      $.each(tabs, function(tabName, tab) {
        var $tab = $('<li>').appendTo($tabs.find('ul:first'));
        var $tabContent = tab();
        var $tabLink = $('<a>')
              .attr({ href: '#project-view-dashboard-' + tabName })
              .html($tabContent.data('tab-title'))
              .appendTo($tab);
        var $content = $('<div>')
              .appendTo($tabs)
              .attr({ id: 'project-view-dashboard-' + tabName })
              .append($tabContent);
      });

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

      $tabs.bind('tabsshow', function(event, ui) {
        var $panel = $(ui.panel);
        var $management = $panel.find('.management');
        var $managementInvite = $panel.find('.management-invite');

        if ($management.size()) {
          $management.children().remove();
          $management.append(pageElems.userManagement({
            context: cloudStack.context
          }));

          return true;
        }

        if ($managementInvite.size()) {
          $managementInvite.children().remove();
          $managementInvite.append(pageElems.userManagement({
            context: cloudStack.context,
            useInvites: true
          }));
        }

        return true;
      });

      return $('<div>').addClass('project-dashboard')
        .append($.merge(
          $toolbar,
          $tabs.tabs()
        ));
    },

    /**
     * Add new project flow
     */
    newProjectForm: function() {
      var $newProject = $('<div>').addClass('new-project');
      $newProject.append($('<div>').addClass('title').html(_l('label.create.project')));

      var $form = $('<form>');
      var $formDesc = $('<div>').addClass('form-desc');
      var $projectName = $('<div>').addClass('field name')
            .append($('<label>').attr('for', 'project-name').html(_l('label.project.name')))
            .append($('<input>').addClass('required').attr({
              type: 'text',
              name: 'project-name',
              id: 'project-name'
            }));
      var $projectDesc = $('<div>').addClass('field desc')
            .append($('<label>').attr('for', 'project-desc').html(_l('label.display.text')))
            .append($('<input>').attr({
              type: 'text',
              name: 'project-display-text',
              id: 'project-desc'
            }));
      var $submit = $('<input>').attr({ type: 'submit' }).val(_l('label.create.project'));
      var $cancel = $('<div>').addClass('button cancel').html(_l('label.cancel'));
      var $loading = $('<div>').addClass('loading-overlay');

      // Form events/validation
      $form.validate();
      $form.submit(function() {
        if (!$form.valid()) return false;

        $form.prepend($loading);

        cloudStack.projects.add({
          context: cloudStack.context,
          data: cloudStack.serializeForm($form),
          response: {
            success: function(args) {
              var project = args.data;

              $(window).trigger('cloudStack.fullRefresh');

              $loading.remove();

              // Confirmation
              $form.replaceWith(function() {
                var $confirm = $('<div>').addClass('confirm');

                // Update title with project name
                $newProject.find('.title').html(_s(args.data.name));

                // Show field data
                $confirm.append($projectName).find('input').replaceWith( // Name
                  $('<span>').addClass('value').html(_s(
                    args.data.name
                  ))
                );
                $confirm.append($projectDesc).find('input').replaceWith( // Display text
                  $('<span>').addClass('value').html(_s(
                    args.data.displayText
                  ))
                );

                var $buttons = $('<div>').addClass('buttons');
                var $addAccountButton = $('<div>').addClass('button confirm').html(_l('label.add.accounts'));

                $addAccountButton.click(function() {
                  // Show add user form
                  $confirm.replaceWith(function() {
                    var $userManagement = pageElems.userManagement({
                      context: $.extend(true, {}, cloudStack.context, {
                        projects: [project]
                      }),
                      useInvites: cloudStack.projects.requireInvitation()
                    });
                    var $nextButton = $('<div>').addClass('button confirm next').html(_l('label.next'));

                    $newProject.find('.title').html(
                      cloudStack.projects.requireInvitation() ?
                        _l('label.invite.to') + ' ' + _s(args.data.name) :
                        _l('label.add.accounts.to') + ' ' + _s(args.data.name)
                    );
                    $nextButton.appendTo($userManagement).click(function() {
                      $newProject.find('.title').html(_l('label.review'));
                      $userManagement.replaceWith(function() {
                        var $review = $('<div>').addClass('review');
                        var $projectData = $('<div>').addClass('project-data');

                        // Basic project data
                        $review.append($projectData);
                        $projectData.append($projectName).find('input').replaceWith( // Name
                          $('<span>').addClass('value').html(_s(
                            args.data.name
                          ))
                        );
                        $projectData.append($projectDesc).find('input').replaceWith( // Display text
                          $('<span>').addClass('value').html(_s(
                            args.data.displayText
                          ))
                        );

                        // User/resouce tabs
                        var $tabs = $('<div>').addClass('tabs resources').appendTo($review);
                        var $ul = $('<ul>').appendTo($tabs)
                              .append(
                                // Users tab
                                $('<li>').addClass('first').append(
                                  $('<a>').attr({ href: '#new-project-review-tabs-users'}).html(
                                    cloudStack.projects.requireInvitation() ?
                                      _l('label.invitations') : _l('label.accounts')
                                  )
                                )
                              );

                        if (isAdmin() || isDomainAdmin()) {
                          $ul.append(
                            // Resources tab
                            $('<li>').addClass('last').append(
                              $('<a>').attr({ href: '#new-project-review-tabs-resouces'}).html(_l('label.resources'))
                            )
                          );
                        }

                        var $users = $('<div>').attr({ id: 'new-project-review-tabs-users' }).appendTo($tabs);
                        cloudStack.context.projects = [project];

                        var $resources;
                        if (isAdmin() || isDomainAdmin()) {
                          $resouces = $('<div>')
                            .attr({ id: 'new-project-review-tabs-resouces' })
                            .appendTo($tabs)
                            .append(pageElems.dashboardTabs.resources);
                        }

                        $tabs.tabs();

                        $users.listView({
                          listView: {
                            id: 'project-accounts',
                            disableInfiniteScrolling: true,
                            fields: !cloudStack.projects.requireInvitation() ? {
                              username: { label: _l('label.account') }
                            } : {
                              account: { label: _l('label.invited.accounts') }
                            },
                            dataProvider: function(args) {
                              setTimeout(function() {
                                args.response.success({
                                  data: $.map($userManagement.find('.data-item tr'), function(elem) {
                                    // Store previous user data in list table
                                    return !cloudStack.projects.requireInvitation() ? {
                                      username: $(elem).find('td.username span').html()
                                    } : {
                                      account: $(elem).find('td.account span').html()
                                    };
                                  })
                                });
                              }, 0);
                            }
                          }
                        });

                        // Save button
                        var $saveButton = $nextButton.clone().appendTo($review);
                        $saveButton.html(_l('label.save'));
                        $saveButton.click(function() {
                          $('#new-project-review-tabs-resouces').find('form').submit();
                          $('.ui-dialog, .overlay').remove();
                        });

                        $laterButton.click(function() {
                          $(':ui-dialog, .overlay').remove();

                          return false;
                        });

                        return $review;
                      });

                      $(':ui-dialog').dialog('option', 'position', 'center');
                    });
                    $laterButton.html(_l('label.close')).appendTo($userManagement);

                    return $userManagement;
                  });

                  $(':ui-dialog').dialog('option', 'position', 'center');

                  return false;
                });

                var $laterButton = $('<div>').addClass('button later').html(_l('label.remind.later'));
                $laterButton.click(function() {
                  $(':ui-dialog, .overlay').remove();

                  return false;
                });

                $buttons.appendTo($confirm).append($.merge(
                  $addAccountButton, $laterButton
                ));

                return $confirm;
              });
            },
            error: cloudStack.dialog.error(function() {
              $loading.remove();
            })
          }
        });

        return false;
      });

      $cancel.click(function() {
        $(':ui-dialog, .overlay').remove();
      });

      return $newProject
        .append(
          $form
            .append($formDesc)
            .append($projectName)
            .append($projectDesc)
            .append($cancel)
            .append($submit)
        );
    },

    /**
     * Project selection list
     */
    selector: function(args) {
      var $selector = $('<div>').addClass('project-selector');
      var $toolbar = $('<div>').addClass('toolbar');
      var $list = $('<div>').addClass('listing')
            .append($('<div>').addClass('header').html(_l('label.name')))
            .append($('<div>').addClass('data').append($('<ul>')));
      var $searchForm = $('<form>');
      var $search = $('<div>').appendTo($toolbar).addClass('search')
            .append(
              $searchForm
                .append($('<input>').attr({ type: 'text' }))
                .append($('<input>').attr({ type: 'submit' }).val(''))
            );
      var $projectSelect = args.$projectSelect;
      var $cancel = $('<div>').addClass('button cancel').html(_l('label.cancel'));

      // Get project data
      var loadData = function(complete) {
        cloudStack.projects.dataProvider({
          context: cloudStack.context,
          response: {
            success: function(args) {
              var data = args.data;

              $projectSelect.find('option').remove();
              $(data).each(function() {
                var displayText = this.displayText ? this.displayText : this.name;

                $('<li>')
                  .data('json-obj', this)
                  .html(_s(displayText))
                  .appendTo($list.find('ul'));

                // Populate project select
                $('<option>')
                  .appendTo($projectSelect)
                  .data('json-obj', this)
                  .html(_s(displayText));
              });

              cloudStack.evenOdd($list, 'li', {
                even: function($elem) {
                  $elem.addClass('even');
                },

                odd: function($elem) {
                  $elem.addClass('odd');
                }
              });

              if (complete) complete();
            }
          }
        });
      };

      // Search form
      $searchForm.submit(function() {
        $list.find('li').remove();
        loadData();

        return false;
      });

      //Cancel button
      $cancel.click(function() {
        $(':ui-dialog, .overlay').remove();
        $('.select.default-view').click();
      });


      // Initial load
      loadData(function() {
        if (!$list.find('li').size()) {
          cloudStack.dialog.notice({
            message: isAdmin() || isDomainAdmin() || g_userProjectsEnabled ?
              _l('message.no.projects') :
              _l('message.no.projects.adminOnly')
          }).closest('.ui-dialog');
          $.merge($selector, $('.overlay')).remove();
          $('.select.default-view').click();
        } else {
          $selector.dialog({
            title: _l('label.select.project'),
            dialogClass: 'project-selector-dialog',
            closeOnEscape: false ,
            width: 420
          }).closest('.ui-dialog').overlay();
        }
      });

      // Project item click event
      $selector.click(function(event) {
        var $target = $(event.target);

        if ($target.is('li')) {
          cloudStack.context.projects = [$target.data('json-obj')];
          showDashboard();

          var $switcher = $('.select.project-view');
          var projectName = _s(cloudStack.context.projects[0].name);

          $switcher.attr('title', projectName);
          if (projectName.length > 10) {
            projectName = projectName.substr(0, 10).concat('...');
          }

          // Put project name in header
          $switcher.html('<span class="icon">&nbsp;</span>' + projectName);


          $.merge($selector, $('.overlay')).remove();

          // Select active project
          $projectSelect
            .find('option').attr('selected', '')
            .filter(function() {
              return $(this).data('json-obj').name == _s(cloudStack.context.projects[0].name);
            }).attr('selected', 'selected');

          ////
          // Hidden for now
          //$projectSelect.parent().show();
        }
      });

      return $selector
        .append($toolbar)
        .append($list)
        .append($cancel);
    }
  };

  /**
   * Show project-mode appearance on CloudStack UI
   */
  var applyProjectStyle = function() {
    var $container = $('#cloudStack3-container');
    $container.addClass('project-view');
  };

  /**
   * Initiate new project flow
   */
  var addProject = function() {
    pageElems.newProjectForm().dialog({
      title: 'New Project',
      closeOnEscape: false,
      width: 760
    }).closest('.ui-dialog').overlay();
  };

  /**
   * Show the dashboard, in panel
   */
  var showDashboard = function() {
    var $browser = $('#browser .container');
    applyProjectStyle($('html body'));

    // Cleanup project context
    if (cloudStack.context.projects)
      cloudStack.context.projects[0].isNew = false;

    $browser.cloudBrowser('removeAllPanels');
    $browser.cloudBrowser('addPanel', {
      title: _l('label.project.dashboard'),
      complete: function($newPanel) {
        $('#navigation li.dashboard').addClass('active').siblings().removeClass('active');
        $newPanel.append(pageElems.dashboard);
      }
    });
  };

  /**
   * Projects entry point
   */
  cloudStack.uiCustom.projects = function(args) {
    var $dashboardNavItem = $('#navigation li.navigation-item.dashboard');

    // Use project dashboard
    var event = function() {
      if (!$('#cloudStack3-container').hasClass('project-view')) {
        // No longer in project view, go back to normal dashboard
        $dashboardNavItem.unbind('click', event);

        return true;
      }

      $(this).addClass('active');
      $(this).siblings().removeClass('active');

      if (cloudStack.context.projects && cloudStack.context.projects[0]) {
        showDashboard();
      }

      return false;
    };
    $dashboardNavItem.bind('click', event);

    pageElems.selector(args);
  };

  /**
   * New project event
   */
  $(window).bind('cloudStack.newProject', function() {
    addProject();
  });
})(cloudStack, jQuery);
