').addClass('loading-overlay');
    var $actions = args.$actions;
    var actionArgs = args.action.action;
    var action = actionArgs.action;
    var actionID = args.action.id;
    var notification = actionArgs.notification;
    var label = actionArgs.label;
    var context = args.context;
    var actionPreFilter = args.actionPreFilter;
    var success = function(args) {
      var remove = args ? args.remove : false;
      var _custom = args ? args._custom : {};
      var updateVMLoadingState = function() {
        var pendingVMs = $tier.data('vpc-tier-pending-vms');
        pendingVMs = pendingVMs ? pendingVMs - 1 : 0;
        if (!pendingVMs) {
          $tier.data('vpc-tier-pending-vms', 0);
          $tier.removeClass('loading');
        } else {
          $tier.data('vpc-tier-pending-vms', pendingVMs);
        }
      };
      cloudStack.ui.notifications.add(
        // Notification
        {
          desc: label,
          poll: notification.poll,
          _custom: _custom
        },
        // Success
        function(args) {
          if (actionID == 'addVM') {
            // Increment VM total
            var $total = $tier.find('.vm-count .total');
            var prevTotal = parseInt($total.html());
            var newTotal = prevTotal + 1;
            var newVM = args.data;
            var newContext = $.extend(true, {}, context, {
              vms: [newVM]
            });
            $total.html(newTotal);
            filterActions({
              $actions: $actions,
              actionPreFilter: actionPreFilter,
              context: newContext
            });
            updateVMLoadingState();
          } else if (actionID == 'remove') { //remove tier
            $loading.remove();
            $tier.remove();
          } else {
            $loading.remove();
          }
        },
        {},
        // Error
        function(args) {
          if (actionID == 'addVM') {
            updateVMLoadingState();
          } else {
            $loading.remove();
          }
        }
      );
    };
    switch(actionID) {
    case 'addVM':
      action({
        context: context,
        complete: function(args) {
          var pendingVMs = $tier.data('vpc-tier-pending-vms');
          pendingVMs = pendingVMs ? pendingVMs + 1 : 1;
          $tier.addClass('loading');
          $tier.data('vpc-tier-pending-vms', pendingVMs);
          success(args);
        }
      });
      break;
    case 'remove':
      $loading.appendTo($tier);
      action({
        context: context,
        response: {
          success: function(args) {
            success($.extend(args, {
              remove: true
            }));
          }
        }
      });
      break;
    case 'acl':
      elems.aclDialog({
        isDialog: true,
        actionArgs: actionArgs,
        context: context  
      }).closest('.ui-dialog').overlay();
      break;
    default:
      $loading.appendTo($tier);
      action({
        context: context,
        complete: success,
        response: {
          success: success,
          error: function(args) { $loading.remove(); }
        }
      });
    }
  };
  // Appends a new tier to chart
  var addNewTier = function(args) {
    var ipAddresses = args.ipAddresses;
    var acl = args.acl;
    var actions = args.actions;
    var vmListView = args.vmListView;
    var actionPreFilter = args.actionPreFilter;
    var context = args.context;
    var $browser = args.$browser;
    var tierDetailView = args.tierDetailView;
    var tier = $.extend(args.tier, {
      ipAddresses: ipAddresses,
      $browser: $browser,
      detailView: tierDetailView,
      context: context,
      vmListView: vmListView,
      actions: actions,
      actionPreFilter: actionPreFilter,
      acl: acl,
      virtualMachines: []
    });
    var $tiers = args.$tiers;
    $tiers.find('li.placeholder')
      .before(
        elems.tier(tier)
          .hide()
          .fadeIn('slow')
      );
  };
  // Renders the add tier form, in a dialog
  var addTierDialog = function(args) {
    var ipAddresses = args.ipAddresses;
    var actions = args.actions;
    var context = args.context;
    var vmListView = args.vmListView;
    var actionPreFilter = args.actionPreFilter;
    var $tiers = args.$tiers;
    var $browser = args.$browser;
    var tierDetailView = args.tierDetailView;
    var acl = args.acl;
    cloudStack.dialog.createForm({
      context: context,
      form: actions.add.createForm,
      after: function(args) {
        var $loading = $('
').addClass('loading-overlay').prependTo($tiers.find('li.placeholder'));
        actions.add.action({
          context: context,
          data: args.data,
          response: {
            success: function(args) {
              var tier = args.data;
              cloudStack.ui.notifications.add(
                // Notification
                {
                  desc: actions.add.label
                },
                // Success
                function(args) {
                  $loading.remove();
                  addNewTier({
                    ipAddresses: ipAddresses,
                    $browser: $browser,
                    tierDetailView: tierDetailView,
                    context: $.extend(true, {}, context, {
                      networks: [tier]
                    }),
                    tier: tier,
                    acl: acl,
                    $tiers: $tiers,
                    actions: actions,
                    actionPreFilter: actionPreFilter,
                    vmListView: vmListView
                  });
                },
                {},
                // Error
                function(args) {
                  $loading.remove();
                }
              );
            },
            error: function(errorMsg) {
              cloudStack.dialog.notice({ message: _s(errorMsg) });
              $loading.remove();
            }
          }
        });
      }
    });
  };
  cloudStack.uiCustom.vpc = function(args) {
    var vmListView = args.vmListView;
    var tierArgs = args.tiers;
    var ipAddresses = args.ipAddresses;
    var gateways = args.gateways;
    var acl = args.acl;
    var siteToSiteVPN = args.siteToSiteVPN;
    var routerDetailView = args.routerDetailView;
    return function(args) {
      var context = args.context;
      var $browser = $('#browser .container');
      var $toolbar = $('
').addClass('toolbar');
      var vpc = args.context.vpc[0];
      $browser.cloudBrowser('addPanel', {
        maximizeIfSelected: true,
        title: 'Configure VPC: ' + vpc.name,
        complete: function($panel) {
          var $loading = $('
').addClass('loading-overlay').appendTo($panel);
          $panel.append($toolbar);
          // Load data
          tierArgs.dataProvider({
            context: context,
            response: {
              success: function(args) {
                // Setup detail view tabs
                var tierDetailView = $.extend(true, {}, tierArgs.detailView, {
                  tabs: {
                    acl: {
                      custom: function(args) {
                        var $acl = elems.aclDialog({
                          isDialog: false,
                          actionArgs: acl,
                          context: args.context
                        });
                        
                        return $acl;
                      }
                    },
                    ipAddresses: {
                      custom: function(args) {
                        return $('
').listView(ipAddresses.listView(),
                                                   {context: args.context});
                      }
                    }
                  }
                });
                
                var tiers = args.tiers;
                var $chart = elems.chart({
                  $browser: $browser,
                  ipAddresses: ipAddresses,
                  gateways: gateways,
                  acl: acl,
                  tierDetailView: tierDetailView,
                  routerDetailView: routerDetailView,
                  siteToSiteVPN: siteToSiteVPN,
                  vmListView: vmListView,
                  context: context,
                  actions: tierArgs.actions,
                  actionPreFilter: tierArgs.actionPreFilter,
                  vpcName: vpc.name,
                  tiers: tiers
                }).appendTo($panel);
                $loading.remove();
                $chart.fadeIn(function() {
                });
              }
            }
          });
        }
      });
    };
  };
}(jQuery, cloudStack));