// 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 addTierDialog = function(args) {
    var $placeholder = args.$placeholder;
    var context = args.context;
    var addAction = cloudStack.vpc.tiers.actions.add;

    cloudStack.dialog.createForm({
      context: context,
      form: addAction.createForm,
      after: function(args) {
        var $loading = $('<div>').addClass('loading-overlay')
          .prependTo($placeholder);

        addAction.action({
          context: context,
          data: args.data,
          $form: args.$form,
          response: {
            success: function(args) {
              cloudStack.ui.notifications.add(
                // Notification
                {
                  desc: addAction.label
                },

                // Success
                function(args) {
                  $loading.remove();
                  $placeholder.closest('.vpc-network-chart').trigger('reload');
                },

                {},

                // Error
                function(args) {
                  $loading.remove();
                }
              );
            },
            error: function(errorMsg) {
              cloudStack.dialog.notice({ message: _s(errorMsg) });
              $loading.remove();
            }
          }
        });
      }
    });
  };

  var elems = {
    tier: function(args) {
      var tier = args.tier;
      var context = $.extend(true, {}, args.context, {
        networks: [tier]
      });
      var dashboardItems = args.dashboardItems;
      var $tier = $('<div>').addClass('tier-item');
      var $header = $('<div>').addClass('header');
      var $title = $('<div>').addClass('title').append($('<span>'));
      var $content = $('<div>').addClass('content');
      var $browser = $('#browser .container');
      var $dashboard = elems.dashboard({
        context: context,
        dashboardItems: dashboardItems
      });
      var $detailLink = $('<div>').addClass('detail-link');
      var $info = $('<div>').addClass('info');
      var $cidrLabel = $('<span>').addClass('cidr-label');
      var $cidr = $('<span>').addClass('cidr');

      $detailLink.click(function() {
        $browser.cloudBrowser('addPanel', {
          title: tier.displayname ? tier.displayname : tier.name,
          complete: function($panel) {
            var $detailView = $('<div>').detailView(
              $.extend(true, {}, cloudStack.vpc.tiers.detailView, {
                section: 'networks',
                $browser: $browser,
                context: context,
                onActionComplete: function() {
                  $tier.closest('.vpc-network-chart').trigger('reload');
                }
              })
            );

            $detailView.appendTo($panel);
          }
        });
      });

      $cidrLabel.html('CIDR: ');
      $cidr.html(tier.cidr);
      $title.find('span').html(tier.displayname ? tier.displayname : tier.name);
      $header.append($title, $detailLink);
      $info.append($cidrLabel, $cidr);
      $content.append($dashboard, $info);
      $tier.append($header, $content);

      return $tier;
    },

    connectorLine: function(args) {
      var $connector = $('<div></div>').addClass('connector-line');
      var $router = args.$router;
      var $tier = args.$tier;
      var isHighlighted = args.isHighlighted;
      var $connectorStart = $('<div></div>').addClass('connector-start');
      var $connectorMid = $('<div></div>').addClass('connector-mid');
      var $connectorEnd = $('<div></div>').addClass('connector-end');

      $connector.append($connectorStart, $connectorMid, $connectorEnd);

      if (isHighlighted) {
        $connector.addClass('highlighted');
      }

      var posStartOffsetLeft = 5;
      var posStartOffsetTop = 10;
      var posStart = {
        top: $router.position().top + ($router.outerHeight() / 2 + ($tier.index() * posStartOffsetTop)),
        left: $router.position().left + $router.outerWidth()
      };
      var posStartWidth = 60 - ($tier.index() > 2 ? (($tier.index() + 1) * posStartOffsetLeft) : 0);

      var posEndOffset = 15;
      var posEndWidthOffset = 3;
      var posEnd = {
        top: $tier.position().top + ($tier.outerHeight() / 2),
        left: posStart.left + posStartWidth + posEndOffset
      };
      var posEndWidth = Math.abs($tier.position().left -
                                 (posStart.left + posStartWidth)) + posEndWidthOffset;

      // Start line (next to router)
      $connectorStart.css({
        top: posStart.top,
        left: posStart.left
      });
      $connectorStart.width(posStartWidth);

      // End line (next to tier)
      $connectorEnd.css({
        top: posEnd.top,
        left: posEnd.left
      });
      $connectorEnd.width(posEndWidth);

      // Mid line (connect start->end)
      if (posStart.top > posEnd.top) { // Tier above router
        $connectorMid.css({
          top: posEnd.top,
          left: posEnd.left
        });
        $connectorMid.height(posStart.top - posEnd.top);
      } else { // Tier below router
        $connectorMid.css({
          top: posStart.top,
          left: posStart.left + posStartWidth + posEndOffset
        });
        $connectorMid.height(posEnd.top - posStart.top);
      }

      return $connector;
    },

    router: function(args) {
      var $router = elems.tier({
        context: args.context,
        tier: {
          name: 'Router',
        },
        dashboardItems: args.dashboardItems
      }).addClass('router');

      $router.find('.info, .detail-link').remove();
      $router.find('.header').prepend($('<span></span>').addClass('icon').html('&nbsp;'));

      return $router;
    },

    tierPlaceholder: function(args) {
      var context = args.context;
      var $placeholder = $('<div>').addClass('tier-placeholder');

      $placeholder.append($('<span>').append('Create network'));
      $placeholder.click(function() {
        addTierDialog({
          context: context,
          $placeholder: $placeholder
        });
      });

      return $placeholder;
    },

    dashboard: function(args) {
      var $dashboard = $('<div>').addClass('dashboard');
      var context = args.context;
      var tier = context.networks[0];

      $(args.dashboardItems).map(function(index, dashboardItem) {
        var $dashboardItem = $('<div>').addClass('dashboard-item');
        var $name = $('<div>').addClass('name').append($('<span>'));
        var $total = $('<div>').addClass('total').append($('<span>'));
        var id = dashboardItem.id;

        $name.find('span').html(dashboardItem.name);


        if (dashboardItem.totalMultiLine) {
          $total.find('span').html(dashboardItem.totalMultiLine);
          $total.addClass('multiline');
        } else {
          $total.find('span').html(dashboardItem.total ? dashboardItem.total : 0);
        }

        $dashboardItem.append($total, $name);
        $dashboardItem.appendTo($dashboard);

        if (dashboardItem._disabled) {
          $dashboardItem.addClass('disabled');
        }

        $dashboardItem.click(function() {
          if ($dashboardItem.is('.disabled')) {
            return false;
          }
          
          var section = cloudStack.vpc.sections[id];
          var $section = $('<div>');
          var $loading = $('<div>').addClass('loading-overlay');

          if ($.isFunction(section)) {
            section = cloudStack.vpc.sections[id]();
          }

          var before = section.before;
          var load = function() {
            $('#browser .container').cloudBrowser('addPanel', {
              title: tier.name + ' - ' + dashboardItem.name,
              maximizeIfSelected: true,
              complete: function($panel) {
                if (section.listView) {
                  $section.listView($.extend(true, {}, section, {
                    onActionComplete: function() {
                      $dashboardItem.closest('.vpc-network-chart').trigger('reload');
                    },
                    context: context
                  }));
                }

                $section.appendTo($panel);
              }
            });
          };

          if (before) {
            before.check({
              context: context,
              response: {
                success: function(result) {
                  // true means content exists
                  if (result) {
                    load();
                  } else {
                    cloudStack.dialog.confirm({
                      message: before.messages.confirm,
                      action: function() {
                        $loading.appendTo($dashboardItem.closest('.vpc-network-chart'));
                        before.action({
                          context: context,
                          response: {
                            success: function() {
                              $loading.remove();
                              $dashboardItem.closest('.vpc-network-chart').trigger('reload');
                              load();
                            }
                          }
                        });
                      }
                    })
                  }
                }
              }
            });
          } else {
            load();
          }
        });
      });

      return $dashboard;
    }
  };

  cloudStack.modules.vpc = function(module) {
    var vpc = cloudStack.vpc;
    var vpcSection = cloudStack.sections.network.sections.vpc;
    var listConfigureAction = vpcSection.listView.actions.configureVpc.action;
    var detailsConfigureAction = vpcSection.listView.detailView.actions.configureVpc.action;

    var vpcChart = function(args) {
      var context = args.context;
      var vpcItem = context.vpc[0];

      var chart = function(args) {
        args = args ? args : {};

        var $chart = $('<div>').addClass('vpc-network-chart');
        var $tiers = $('<div>').addClass('tiers');
        var $toolbar = $('<div>').addClass('toolbar');
        var $info = $('<div>').addClass('info-box');

        $toolbar.appendTo($chart);
        $tiers.appendTo($chart);

        // Get tiers
        var $loading = $('<div>').addClass('loading-overlay').prependTo($chart);
        vpc.tiers.dataProvider({
          context: context,
          response: {
            success: function(data) {
              var tiers = data.tiers;
              var $router;
              var $placeholder = elems.tierPlaceholder({
                context: context
              });

              // Router
              $router = elems.router({
                context: context,
                dashboardItems: data.routerDashboard
              }).appendTo($chart);

              $(tiers).map(function(index, tier) {
                var $tier = elems.tier({
                  context: context,
                  tier: tier,
                  dashboardItems: tier._dashboardItems
                });
                $tier.appendTo($tiers);

                // Connect tier to router via line
                //
                // -- Needs to execute after chart generation is complete,
                //    so that chart elements have positioning in place.
                $chart.bind('cloudStack.vpc.chartReady', function() {
                  elems.connectorLine({
                    $tier: $tier,
                    $router: $router,
                    isHighlighted: tier._highlighted
                  }).appendTo($chart);
                });
              });

              // Add placeholder tier
              $tiers.append($placeholder);
              $loading.remove();

              if (!tiers.length) {
                addTierDialog({
                  context: context,
                  $placeholder: $placeholder
                });
              }

              if (args.complete) {
                args.complete($chart);
              }

              if ($chart.find('.connector-line.highlighted').size()) {
                $info.appendTo($chart).append(
                  $('<span>').addClass('color-key'),
                  $('<span>').html('= Contains a public network')
                );
              }
            }
          }
        });

        $chart.bind('reload', function() {
          chart({
            complete: function($newChart) {
              $chart.replaceWith($newChart);
              $newChart.trigger('cloudStack.vpc.chartReady');
            }
          });
        });

        return $chart;
      };

      $('#browser .container').cloudBrowser('addPanel', {
        title: vpcItem.displaytext ? vpcItem.displaytext : vpcItem.name,
        maximizeIfSelected: true,
        complete: function($panel) {
          var $chart = chart({
            complete: function($chart) {
              $chart.trigger('cloudStack.vpc.chartReady');
            }
          });

          $chart.appendTo($panel);
        }
      });
    };

    listConfigureAction.custom = vpcChart;
    detailsConfigureAction.custom = vpcChart;
  };
}(jQuery, cloudStack));
