text: /********************************************************* {COPYRIGHT-TOP} ***
   * Licensed Materials - Property of IBM
   * 5725-Z22, 5725-Z63, 5725-U33, 5725-Z63
   *
   * (C) Copyright IBM Corporation 2015, 2017
   *
   * All Rights Reserved.
   * US Government Users Restricted Rights - Use, duplication or disclosure
   * restricted by GSA ADP Schedule Contract with IBM Corp.
   ********************************************************** {COPYRIGHT-END} **/
  // Node module: apim-ui
  
  'use strict';
  
  angular.module('apim.core', [
    'apic.projects'
  ]).controller('ApimController', [
    '$scope',
    '$rootScope',
    '$http',
    '$q',
    '$interval',
    '$location',
    '$state',
    '$mdSidenav',
    '$modal',
    '$log',
    '$window',
    '$localStorage',
    '$mdDialog',
    'sinceFilter',
    'ContextMenu',
    'ProjectsServices',
    'ConfigServices',
    'ProcessManager',
    'AppRunnerStates',
    'TrackingServices',
    'tmhDynamicLocale',
    function ApimController($scope, $rootScope, $http, $q, $interval, $location,
      $state, $mdSidenav, $modal, $log, $window, $localStorage, $mdDialog, sinceFilter,
      ContextMenu, ProjectsServices, ConfigServices, ProcessManager, AppRunnerStates, TrackingServices,
      tmhDynamicLocale) {
  
        $scope.isSaaS = window.isSaaS;
  
        $scope.menuPinned = $scope.isSaaS;
  
        $scope.helpEnabled = true;
  
        $scope.chatMenuIsOpen = false;
  
        tmhDynamicLocale.set($localStorage.getItem('ngStorage-userLocale'));
  
        $rootScope.features = {
          "vendorExtensions": true,
          "customPolicies": false, // may be enabled later by currentUserController based on form factor
          "standaloneMicroGateway": true,
          "offlineWSDL": true,
          "multipleGatewayCatalogs": false,
          "multipleEndpoints": false,
          "applicationLifecycle": false, // may be enabled later by currentUserController based on form factor
          "spaces": true,
          "certificates": false,
          "kerberos-keytabs": false,
          "private-keys": false,
          "components": false, // $ref support in drafts, external assemblies, and top-level components
          "shared-secret": false,
          "useJWT101": false,
          "kibanav5": true,
          "experimental": false,
          "monetization": true,
          "analyticsSection": true,
          "NPS": false // NPS will be moved to Bluemix APIs dashboard; please see: https://github.ibm.com/apimesh/apim-ui/issues/4359#issuecomment-3230754
        };
        // check if any of the above feature flags were added into the query part of the URL
        var search = window.location.search;
        if (search) {
          var URLQueries = {};
          search = search.substr(1);	// slice out the question mark
          var nameValuePairs = search.split("&");
          var len = nameValuePairs.length;
          for (var i=0;i<len;i++) {
            var nameValue = nameValuePairs[i].split("=");
            URLQueries[nameValue[0]] = nameValue[1];
          } // end for
          for (var key in URLQueries) {
            if ($scope.features.hasOwnProperty(key)) {
              var value = URLQueries[key];
              if (value === "true") {
                $scope.features[key] = true;
              } else if (value === "false") {
                $scope.features[key] = false;
              }
            }
          } // end for
        }
        if ($rootScope.offlineMode) {
          $http.get('/apic-config/get?key=datapower-api-gateway-experimental').then(function(apicConfig) {
            $rootScope.features.experimental = apicConfig.data === 'true';
            $scope.experimental = $rootScope.features.experimental;
          });
        }
  
        $http.get('apim/swagger-schema-v2.0-ibm.json').then(function(response) {
          $scope.swaggerSchema = response.data;
        });
  
        $scope.$on('menu-configuration', function($event, configuration) {
          $scope.menuConfiguration = configuration;
        });
  
        $scope.contextVariables = ContextMenu.variables;
  
        $scope.animate = true;
        $scope.location = $location;
        $scope.currentSection = 'catalogs';
        if (window.location.hash.indexOf("#/operations") == 0) {
          $scope.currentSection = 'operations';
        } else if (window.location.hash.indexOf("#/community") == 0) {
          $scope.currentSection = 'community';
        } else if (window.location.hash.indexOf("#/admin") == 0) {
          $scope.currentSection = 'admin';
        } else if (window.location.hash.indexOf("#/design") == 0) {
          $scope.currentSection = 'design';
        } else if (window.location.hash.indexOf("#/catalogs") == 0) {
          $scope.currentSection = 'catalogs';
        } else if (window.location.hash.indexOf("#/analytics") == 0) {
          $scope.currentSection = 'analytics';
        } else if (window.location.hash.indexOf("#/projects") == 0) {
          $scope.currentSection = 'projects';
        }
        if (window.location.hash.indexOf("#/gui") == 0) {
          $scope.editView = 'gui';
        } else {
          $scope.editView = 'raw';
        }
  
        if(typeof(Storage) !== "undefined") {
          $scope.menuPinned = localStorage.getItem("apim-pinned-nav") == "true";
        }
        $scope.visibleSection = $scope.currentSection;
        $scope.setVisibleSection = function(section) {
          $scope.visibleSection = section;
        };
  
        $scope.toggleFavouriteSection = function() {
          $scope.visibleSection = ($scope.visibleSection !== 'favourites') ? 'favourites' : undefined;
        };
  
        $scope.setMainTab = function(value) {
          $scope.mainTab = value;
          TrackingServices.page('mainTab', value);
        };
        $scope.setCurrentItem = function(currentItem) {
          $scope.currentItem = currentItem;
        };
        $scope.setEnvironment = function(currentEnvironment) {
          $scope.environment = currentEnvironment;
          if(currentEnvironment) {
            $scope.$watch('environment.name', function() {
              if ($scope.environment) $scope.setCurrentItem({title: $scope.environment.name});
            })
          } else {
            $scope.setCurrentItem(null);
          }
        };
        $scope.setGatewayClusters = function(clusters) {
          $scope.gatewayClusters = clusters;
        };
  
        $scope.navigate = function(target, section, hash) {
          if (hash) {
            window.location.hash = '#/' + hash;
          } else {
            window.location.hash = '#/' + target;
          }
          $mdSidenav('mainNav').close();
        };
  
        $scope.goBack = function() {
          $window.history.back();
        };
  
        $scope.inState = $state.includes;
  
  
        $scope.toggleSideNav = function(sideNavName) {
          // force unpin from hamburger
          if ($scope.menuPinned) {
            $scope.menuPinned = false;
            if(typeof(Storage) !== "undefined") {
              localStorage.setItem("apim-pinned-nav", $scope.menuPinned);
            }
            $mdSidenav('mainNav').close();
          } else {
            $mdSidenav(sideNavName).toggle();
          }
        };
  
        $scope.pinSideNav = function() {
          $scope.menuPinned = !$scope.menuPinned;
          if(!$scope.menuPinned) $mdSidenav('mainNav').close();
  
          if(typeof(Storage) !== "undefined") {
            localStorage.setItem("apim-pinned-nav", $scope.menuPinned);
          }
        };
  
        $scope.onRouteChangeStart = function(event, next, current) {
          $scope.setEnvironment(null);
  
          var hashArray = $scope.location.$$path.split("/");
          $scope.currentSection = hashArray[1];
          $scope.mainTab = (hashArray.length > 3 ? hashArray[3] : hashArray[2]);
          // keep an eye on route query parameters to keep the scope consistent with the hash
          if (!$scope.location.$$search.env) return
          var targetEnv = $scope.location.$$search.env;
          if ($scope.unbindWatch) $scope.unbindWatch();
          $scope.unbindWatch = $scope.$watch('environments', function() {
            if (!$scope.environments) return;
            $scope.environments.$promise.then(function() {
              var envs = $scope.environments.filter(function(environment) {
                return (environment.shortName == targetEnv);
              });
              if (envs.length == 1) $scope.environment = envs[0];
              $scope.unbindWatch();
              delete $scope.unbindWatch;
            });
          });
        };
        $scope.$on("$locationChangeSuccess", $scope.onRouteChangeStart);
  
        // store details around deployed plan and API versions of interest at this higher scope
        $scope.expandedDeployments = [];
        $scope.isExpanded = function(documentId) {
          return $scope.expandedDeployments.indexOf($scope.environment.id + "/" + documentId) >= 0;
        };
  
        // check for analytics enabled
        $rootScope.$watch('analytics', function(enabled){
          if (typeof enabled === 'undefined'){
            return;
          }
  
          if (!enabled && window.location.href.indexOf('/account/settings') === -1){
            ConfigServices.getByName('analytics-reminder', true)
              .then(function(result){
                var now = moment();
                var reminder = result.data && moment(result.data) || null;
  
                // check that the reminder delay has expired before asking again
                if (!reminder || reminder.unix() < now.unix()){
                  $modal.open({
                    templateUrl: ('apim/account/partials/analytics-reminder.html'),
                    windowTemplateUrl: 'apim/partials/main-template.html',
                    controller: 'AnalyticsReminderController',
                    size: 'md',
                    scope: $scope
                  });
                }
              });
          }
        });
  
        // callbacks for message area
        function updateTimestamps() {
          if ($rootScope.latestMessage) $rootScope.latestMessage.time = sinceFilter($rootScope.latestMessage.timestamp);
          if ($rootScope.expandedMessages) {
            $rootScope.messages.forEach(function(message) {
              message.time = sinceFilter(message.timestamp);
            });
          }
          setTimeout(updateTimestamps, 60000);
        }
        $scope.updateAndExpand = function() {
          updateTimestamps();
          $rootScope.expandedMessages = !$rootScope.expandedMessages;
        };
        setTimeout(updateTimestamps, 60000);
        $scope.closeMessageArea = function(event) {
          event.preventDefault();
          $rootScope.expandedMessages = false;
          if ($rootScope.latestMessage) $rootScope.messages.splice(0, 0, $rootScope.latestMessage);
          delete $rootScope.latestMessage;
        };
        $scope.isEmpty = function(obj) {
          return angular.equals({}, obj);
        };
  
        var helpOverlayActive = false;
        $scope.showHelp = function(details) {
          if (helpOverlayActive || $localStorage.getItem(details.id)) {
            return;
          }
  
          helpOverlayActive = true;
  
          var scope = $scope.$new();
          scope.helpId = details.id;
          scope.helpContext = details.context;
  
          $modal.open({
            templateUrl: (details.template || 'apim/partials/help.html'),
            windowTemplateUrl: 'apim/help/partials/help-template.html',
            controller: 'HelpController',
            size: 'md',
            scope: scope
          }).result.finally(function() {
            helpOverlayActive = false;
          });
        };
        // mark any files in the file list as inactive - ui-uploader always adds active:true when uploading
        // a file so we must reset it before trying again on error.
          $rootScope.markFilesInactive = function(files) {
            if (files && files.length) {
              var len = files.length;
              for (var i=0;i<len;i++) {
                var file = files[i];
                if (file.active) {
                  file.active = false;
                }
              } // end for
            }
          };
  
        // show a dialog where the user can copy a URL easily
        $scope.showURLBox = function(url, title, message) {
  
          var scope = $scope.$new();
          scope.dialogContent = {
            url: url,
            title: title,
            message: message
          };
  
          $modal.open({
            controller: 'ShowURLController',
            templateUrl: 'apim/partials/showURLDialog.html',
            windowTemplateUrl: 'apim/partials/main-template.html',
            scope: scope
          });
        };
  
        $scope.showSubnavHeader = function(section, tab) {
          var show = [
            'apis',
            'components',
            'products',
            'security',
            'assemblies',
            'models',
            'datasources',
            'run'
          ].some(function(item) {
            return (section === 'design' && tab === item) || !tab && section === item;
          });
  
          return show;
        };
  
        $scope.showProjectSettings = function() {
          $rootScope.$emit('event:projects:showProjectSettings', $scope);
        };
  
        $scope.useNavView = function() {
          return ($state.current.views &&
            $state.current.views.hasOwnProperty('navView'));
        };
  
        // handlers for SaaS signup
        $scope.saasSignup = {
          disclaimerAccepted: false,
          agreementAccepted: false
        };
        $scope.signupForSaas = function() {
          $scope.signingUp = true;
          $scope.signingUpLock = true;
          var config = {
            "headers": {
              "Content-Type": "application/json"
            }
          };
          $http.post("proxy/providerOrg/betaRegistration", $scope.saasSignup, config).then(function(response) {
            $scope.signingUp = false;
            $scope.signupMessage = response.data.message;
            $scope.signupSuccess = true;
          }, function(err) {
            $scope.signingUp = false;
          });
        };
        $scope.showSaasTC = function() {
          $window.open("https://developer.ibm.com/apimanagement/3737-2/");
        };
  
        $scope.ready = true;
  
        // listen to tracking events from assembler
        $rootScope.$on('event:track', function($event, ns, key, data){
          TrackingServices.track(ns, key, data);
        });
  
        $rootScope.$on('event:getAllProjects', function(){
          if (!$rootScope.offlineMode) return;
  
          ProjectsServices.getWorkspaceEnvironment()
            .then(function(project){
              if ( !project.path && !project.basePath ) return getProjectList();
  
              getProjectList()
                .then(function(){
                  ConfigServices.inspectPath(project.path)
                    .then(function(result) {
                      var project = result;
                      var matchedProjects = $rootScope.projects.filter(function(p){
                        return project.basePath === p.path;
                      });
  
                      //find project from in projects list
                      var knownProject = _.filter(matchedProjects, { path: project.basePath})[0] || null;
  
                      // if project is already in list, set as active project
                      if (knownProject){
                        return ProjectsServices.setProjectEnvironment(knownProject)
                          .then(function(activeProject){
                            $rootScope.activeProject = activeProject;
                            return activeProject;
                          });
                      }
  
                      // create a pseudo project if type is unknown or loopback
                      if (!matchedProjects.length && (project.projectType === 'unknown' || project.projectType === 'loopback')) {
                        var newProject = {
                          displayName: project.name || project.basePath,
                          name: project.name || $rootScope.generateProjectName(project.basePath),
                          path: project.basePath,
                          type: project.type,
                          projectType: project.projectType
                        };
  
                        return ProjectsServices.addProject(newProject)
                          .then(function(addProjectResult) {
                            return ProjectsServices.setProjectEnvironment(addProjectResult.data);
                          })
                          .then(function(result) {
                            $rootScope.activeProject = result;
                            getProjectList();
                          })
                          .catch(function(err) {
                            $log.error('add project failed', err);
                          });
                      }
  
                      getProjectList();
                    })
                    .catch(function(err){
                      $log.error(err);
                    });
                });
            });
        });
  
        $scope.backToOverview = function() {
          window.parent.postMessage({
            action: 'navigate',
            where: 'overview'
          }, '*');
        };
  
        $scope.tryDesigner = function() {
          window.parent.postMessage({
            action: 'navigate',
            where: 'designer'
          }, '*');
        };
  
        // todo remove once login actually works (see app.js for event emitter)
        $rootScope.$emit('event:getAllProjects');
  
        $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
          if (toState.name !== fromState.name && fromState.name !== '') {
            if ((toState.name === 'api' && window.angular2Loaded) ||
              (toState.name === 'explorer' && !window.angular2Loaded)) {
              $scope.ready = false;
              window.location.reload();
            }
          }
        });
  
        $rootScope.$watch('activeProject', function(newProject){
          if (!$rootScope.offlineMode || !newProject) return;
  
          $log.log('activeProject updated', newProject);
          $rootScope.workspaceDir = newProject;
          $rootScope.$emit('event:reloadStagingTargets');
        });
  
        $rootScope.isLoopbackProject = function(){
          return $rootScope.activeProject.projectType === "loopback";
        };
  
        function getProjectList(){
          var def = $q.defer();
  
          if (!$rootScope.offlineMode) {
            def.resolve();
            return def.promise;
          }
  
          ProjectsServices.getWorkspaceEnvironment()
            .then(function(result){
              //manually set localStorage for when starting up in project directory
              $rootScope.workspaceDir = result;
  
              ConfigServices.inspectPath(result.path)
                .then(function(pathResult){
                  ProjectsServices.setProjectEnvironment(pathResult)
                    .then(function(projectEnvResult){
                      $rootScope.activeProject = projectEnvResult;
                      return projectEnvResult;
                    })
                })
                .catch(function(err){
                  $log.error(err);
  
                  if (err.data.indexOf('ENOENT: no such file or directory')) {
                    $log.log('File system error: ', err);
                  }
                })
            })
            .then(function(){
              return ProjectsServices.getProjects()
                .then(function(result){
                  $rootScope.projects = result.data;
  
                  var activeProject = $localStorage.getItem('activeProject');
  
                  if (!$rootScope.workspaceDir) {
                    def.resolve();
                    $scope.navigate('projects/new');
                  }
  
                  def.resolve();
                });
            })
            .catch(function(err){
              $log.log('getWorkspace error: ', err);
            });
  
          return def.promise;
        }
  
        $scope.processes = [];
        //for showing log
        $scope.logProcesses = [];
        // globabl tracking of running processes
        $scope.isStarting = function() {
          return $scope.processes.length > 0;
        };
  
        $scope.appStarting = false;
        $scope.isRunning = function() {
          var gwRunning = false, appRunning = false;
          $scope.processes.forEach(function(process) {
            if (process != null && process.port != null) {
              if (process.gw) {
                gwRunning = true
              } else {
                appRunning = true;
              }
            }
          });
          return gwRunning && appRunning;
        }
  
        $scope.checkIsRunning = function() {
          ProcessManager.processList().$promise
            .then(function(response) {
              var scheme = function(process) {
                return process.gw ? 'https' : 'http';
              };
  
              $scope.logProcesses = [];
              $scope.processes = [];
              response.processes.forEach(function(process) {
                if (process != null) {
                  var url = scheme(process) + '://' + $location.host();
                  url += (process.port ? ':' + process.port : '') + '/';
                  angular.extend(process, {
                    url: url,
                    gw: process.gw || process.name.slice(-3) === '-gw'
                  });
                  if (process.port) {
                    $scope.processes.push(process);
                  }
                  $scope.logProcesses.push(process);
                }
              });
  
              if ($scope.isStarting()) {
                $scope.status = AppRunnerStates.running;
                $scope.appStarting = !$scope.isRunning();
              } else {
                $scope.status = AppRunnerStates.stopped;
                $scope.appStarting = false;
              }
            });
        };
  
        $scope.$watch('appStarting', function() {
          $scope.$broadcast('starting', $scope.appStarting);
        });
  
        var pollingInterval = null;
        if ($rootScope.offlineMode) {
          $rootScope.$watch('activeProject', function() {
            $scope.processes = [];
  
            if (!pollingInterval) {
              pollingInterval = $interval($scope.checkIsRunning, 5000);
            }
          });
        }
  
        $scope.$watch('processes', function(newVal) {
          newVal.forEach(function(process) {
            if (process.gw && !localStorage.getItem('apim_local_gateway')) {
              localStorage.setItem('apim_local_gateway', $location.host() + ':' + process.port);
            }
          });
        }, true);
  
        // show What's new modal
        $scope.showWhatsNewInfo = function(fromHelp, APIC_VERSION) {
          var scope = $scope.$new();
          var prevShown = $localStorage.getItem('apim_help_whatsnew_shown');
          var prevVer = $localStorage.getItem('apim_version');
          var newVer = APIC_VERSION;
          var whatsNewLink = 'https://developer.ibm.com/apiconnect/whats-new/';
          $rootScope.whatsNewShown = prevShown;
  
          if (!fromHelp) {
            if (prevShown && Number(newVer) <= Number(prevVer)) {
              return;
            }
  
            $rootScope.whatsNewShown = true;
            $localStorage.setItem('apim_version', newVer);
            $localStorage.setItem('apim_help_whatsnew_shown', true);
          }
  
          var whatsNewTitle = $scope.isSaaS ? 'whatsnewbluemixtitle' : 'whatsnewonpremtitle';
          $scope.notifyUser(whatsNewTitle, [], 'INFO', false, '', whatsNewLink, 26000);
  
        }
  
        $rootScope.$on('event:showWhatsNewifApplicable', function(event) {
          // TODO: Create service to dynamically access API Connect version
          var APIC_VERSION = 5071; // update this every release
          $scope.showWhatsNewInfo(false, APIC_VERSION);
        });
    }]);
  
  angular.module('apim').controller('HelpController', ['$scope', '$rootScope', '$http', '$location', '$mdSidenav', '$modalInstance', 'sinceFilter',
    function HelpController($scope, $rootScope, $http, $location, $mdSidenav, $modalInstance, sinceFilter) {
      $scope.closeHelp = function() {
        if(typeof(Storage) !== "undefined") {
          localStorage.setItem($scope.helpId, "true");
        }
        $modalInstance.dismiss('ok');
      }
    }
  ]);
  
  angular.module('apim').controller('ShowURLController', ['$scope', '$modalInstance',
    function ShowURLController($scope, $modalInstance) {
  
      $scope.close = function() {
        $modalInstance.close();
      };
    }
  ]);
  