// 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, $) {
  cloudStack.uiCustom.enableStaticNAT = function(args) {
    var listView = args.listView;
    var action = args.action;
    var tierSelect = args.tierSelect;

    return function(args) {
      var context = args.context;
      var $instanceRow = args.$instanceRow;

      var vmList = function(args) {
        // Create a listing of instances, based on limited information
        // from main instances list view
        var $listView;
        var instances = $.extend(true, {}, args.listView, {
          context: context,
          uiCustom: true
        });

        instances.listView.actions = {
          select: {
            label: _l('label.select.instance'),
            type: 'radio',
            action: {
              uiCustom: function(args) {
                var $item = args.$item;
                var $input = $item.find('td.actions input:visible');

                if ($input.attr('type') == 'checkbox') {
                  if ($input.is(':checked'))
                    $item.addClass('multi-edit-selected');
                  else
                    $item.removeClass('multi-edit-selected');
                } else {
                  $item.siblings().removeClass('multi-edit-selected');
                  $item.addClass('multi-edit-selected');
                }
              }
            }
          }
        };

        $listView = $('<div>').listView(instances);

        // Change action label
        $listView.find('th.actions').html(_l('label.select'));

        return $listView;
      };

      var $dataList = vmList({
        listView: listView
      }).dialog({
        dialogClass: 'multi-edit-add-list panel',
        width: 825,
        title: _l('label.select.vm.for.static.nat'),
        buttons: [
          {
            text: _l('label.apply'),
            'class': 'ok',
            click: function() {
              if ($dataList.find('.tier-select select').val() == -1) {
                cloudStack.dialog.notice({ message: ('Please select a tier')});
                 return false;
               } 

              if (!$dataList.find(
                'input[type=radio]:checked, input[type=checkbox]:checked'
              ).size()) {
                cloudStack.dialog.notice({ message: _l('message.select.instance')});

                return false;
              }

              var complete = args.complete;
              var start = args.start;

              start();
              $dataList.fadeOut(function() {                
                action({
                  tierID: $dataList.find('.tier-select select').val(),
                  _subselect: $dataList.find('tr.multi-edit-selected .subselect select').val(),
                  context: $.extend(true, {}, context, {
                    instances: [
                      $dataList.find('tr.multi-edit-selected').data('json-obj')
                    ]
                  }),
                  response: {
                    success: function(args) {
                      complete({
                        $item: $instanceRow
                      });
                    },
                    error: function(args) {
                      cloudStack.dialog.notice({ message: args });
                    }
                  }
                });
                $dataList.remove();
              });

              $('div.overlay').fadeOut(function() {
                $('div.overlay').remove();
              });
            }
          },
          {
            text: _l('label.cancel'),
            'class': 'cancel',
            click: function() {
              $dataList.fadeOut(function() {
                $dataList.remove();
              });
              $('div.overlay').fadeOut(function() {
                $('div.overlay').remove();
              });
            }
          }
        ]
      }).parent('.ui-dialog').overlay();

      // Add tier select dialog
      if (tierSelect) {
        var $toolbar = $dataList.find('.toolbar');
        var $tierSelect = $('<div>').addClass('filters tier-select').prependTo($toolbar);
        var $tierSelectLabel = $('<label>').html('Select tier').appendTo($tierSelect);
        var $tierSelectInput = $('<select>').appendTo($tierSelect);

        // Get tier data
        tierSelect({
          context: context,
          $tierSelect: $tierSelect,
          response: {
            success: function(args) {
              var data = args.data;

              $(data).map(function(index, item) {
                var $option = $('<option>');

                $option.attr('value', item.id);
                $option.html(item.description);
                $option.appendTo($tierSelectInput);
              });
            },
            error: function(message) {
              cloudStack.dialog.notice({
                message: message ? message : 'Could not retrieve VPC tiers'
              });
            }
          }
        });
      }
    };
  };
}(cloudStack, jQuery));
