text: /**
   * API utilities service
   *
   * @module app/common/services/api-utils
   * @exports APIUtils
   * @name APIUtils
   */
  
  window.angular && (function(angular) {
    'use strict';
    angular.module('app.common.services').factory('APIUtils', [
      '$http', 'Constants', '$q', 'dataService', '$interval',
      function($http, Constants, $q, DataService, $interval) {
        var getScaledValue = function(value, scale) {
          scale = scale + '';
          scale = parseInt(scale, 10);
          var power = Math.abs(parseInt(scale, 10));
  
          if (scale > 0) {
            value = value * Math.pow(10, power);
          } else if (scale < 0) {
            value = value / Math.pow(10, power);
          }
          return value;
        };
        var SERVICE = {
          API_CREDENTIALS: Constants.API_CREDENTIALS,
          API_RESPONSE: Constants.API_RESPONSE,
          CHASSIS_POWER_STATE: Constants.CHASSIS_POWER_STATE,
          HOST_STATE_TEXT: Constants.HOST_STATE,
          LED_STATE: Constants.LED_STATE,
          LED_STATE_TEXT: Constants.LED_STATE_TEXT,
          HOST_SESSION_STORAGE_KEY: Constants.API_CREDENTIALS.host_storage_key,
          getChassisState: function() {
            var deferred = $q.defer();
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/state/chassis0/attr/CurrentPowerState',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      deferred.resolve(content.data);
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
          validIPV4IP: function(ip) {
            // Checks for [0-255].[0-255].[0-255].[0-255]
            return ip.match(
                /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/);
          },
          getRedfishSysName: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() + '/redfish/v1/Systems',
                     withCredentials: true
                   })
                .then(
                    function(response) {
                      var sysUrl = response.data['Members'][0]['@odata.id'];
                      return sysUrl.split('/').pop(-1);
                    },
                    function(error) {
                      console.log(JSON.stringify(error));
                    });
          },
          getSystemLogs: function(recordType) {
            var uri = '/redfish/v1/Systems/' + DataService.systemName +
                '/LogServices/EventLog/Entries';
            return $http({
                     method: 'GET',
                     url: DataService.getHost() + uri,
                     withCredentials: true
                   })
                .then(
                    function(response) {
                      var logEntries = [];
                      angular.forEach(response.data['Members'], function(log) {
                        if (log.hasOwnProperty('EntryType')) {
                          if (log['EntryType'] == recordType) {
                            logEntries.push(log);
                          }
                        }
                      });
                      return logEntries;
                    },
                    function(error) {
                      console.log(JSON.stringify(error));
                    });
          },
          clearSystemLogs: function() {
            var uri = '/redfish/v1/Systems/' + DataService.systemName +
                '/LogServices/EventLog/Actions/LogService.ClearLog';
            return $http({
              method: 'POST',
              url: DataService.getHost() + uri,
              withCredentials: true
            });
          },
          deleteObject: function(path) {
            return $http({
                     method: 'POST',
                     url: DataService.getHost() + path + '/action/Delete',
                     withCredentials: true,
                     data: JSON.stringify({'data': []})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getHostState: function() {
            var deferred = $q.defer();
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/state/host0/attr/CurrentHostState',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      deferred.resolve(content.data);
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
          getSNMPManagers: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/snmp/manager/enumerate',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          pollHostStatusTillOn: function() {
            var deferred = $q.defer();
            var hostOnTimeout = setTimeout(function() {
              ws.close();
              deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_ON_TIMEOUT));
            }, Constants.TIMEOUT.HOST_ON);
  
            var ws =
                new WebSocket('wss://' + DataService.server_id + '/subscribe');
            var data = JSON.stringify({
              'paths': ['/xyz/openbmc_project/state/host0'],
              'interfaces': ['xyz.openbmc_project.State.Host']
            });
            ws.onopen = function() {
              ws.send(data);
            };
            ws.onmessage = function(evt) {
              var content = JSON.parse(evt.data);
              var hostState = content.properties.CurrentHostState;
              if (hostState === Constants.HOST_STATE_TEXT.on_code) {
                clearTimeout(hostOnTimeout);
                ws.close();
                deferred.resolve();
              } else if (hostState === Constants.HOST_STATE_TEXT.error_code) {
                clearTimeout(hostOnTimeout);
                ws.close();
                deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_QUIESCED));
              }
            };
          },
  
          pollHostStatusTilReboot: function() {
            var deferred = $q.defer();
            var onState = Constants.HOST_STATE_TEXT.on_code;
            var offState = Constants.HOST_STATE_TEXT.on_code;
            var hostTimeout;
            var setHostTimeout = function(message, timeout) {
              hostTimeout = setTimeout(function() {
                ws.close();
                deferred.reject(new Error(message));
              }, timeout);
            };
            var ws =
                new WebSocket('wss://' + DataService.server_id + '/subscribe');
            var data = JSON.stringify({
              'paths': ['/xyz/openbmc_project/state/host0'],
              'interfaces': ['xyz.openbmc_project.State.Host']
            });
            ws.onopen = function() {
              ws.send(data);
            };
            setHostTimeout(
                Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT,
                Constants.TIMEOUT.HOST_OFF);
            var pollState = offState;
            ws.onmessage = function(evt) {
              var content = JSON.parse(evt.data);
              var hostState = content.properties.CurrentHostState;
              if (hostState === pollState) {
                if (pollState === offState) {
                  clearTimeout(hostTimeout);
                  pollState = onState;
                  setHostTimeout(
                      Constants.MESSAGES.POLL.HOST_ON_TIMEOUT,
                      Constants.TIMEOUT.HOST_ON);
                }
                if (pollState === onState) {
                  clearTimeout(hostTimeout);
                  ws.close();
                  deferred.resolve();
                }
              } else if (hostState === Constants.HOST_STATE_TEXT.error_code) {
                clearTimeout(hostTimeout);
                ws.close();
                deferred.reject(new Error(Constants.MESSAGES.POLL.HOST_QUIESCED));
              }
            };
          },
  
          pollHostStatusTillOff: function() {
            var deferred = $q.defer();
            var hostOffTimeout = setTimeout(function() {
              ws.close();
              deferred.reject(
                  new Error(Constants.MESSAGES.POLL.HOST_OFF_TIMEOUT));
            }, Constants.TIMEOUT.HOST_OFF);
  
            var ws =
                new WebSocket('wss://' + DataService.server_id + '/subscribe');
            var data = JSON.stringify({
              'paths': ['/xyz/openbmc_project/state/host0'],
              'interfaces': ['xyz.openbmc_project.State.Host']
            });
            ws.onopen = function() {
              ws.send(data);
            };
            ws.onmessage = function(evt) {
              var content = JSON.parse(evt.data);
              var hostState = content.properties.CurrentHostState;
              if (hostState === Constants.HOST_STATE_TEXT.off_code) {
                clearTimeout(hostOffTimeout);
                ws.close();
                deferred.resolve();
              }
            };
          },
          addSNMPManager: function(address, port) {
            return $http({
                     method: 'POST',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/snmp/manager/action/Client',
                     withCredentials: true,
                     data: JSON.stringify({'data': [address, +port]})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setSNMPManagerPort: function(snmpManagerPath, port) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() + snmpManagerPath + '/attr/Port',
                     withCredentials: true,
                     data: JSON.stringify({'data': +port})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setSNMPManagerAddress: function(snmpManagerPath, address) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() + snmpManagerPath +
                         '/attr/Address',
                     withCredentials: true,
                     data: JSON.stringify({'data': address})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getNetworkInfo: function() {
            var deferred = $q.defer();
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/network/enumerate',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      var hostname = '';
                      var defaultgateway = '';
                      var macAddress = '';
  
                      function parseNetworkData(content) {
                        var data = {
                          interface_ids: [],
                          interfaces: {},
                          ip_addresses: {ipv4: [], ipv6: []},
                        };
                        var interfaceId = '', keyParts = [], interfaceHash = '',
                            interfaceType = '';
                        for (var key in content.data) {
                          if (key.match(/network\/eth\d+(_\d+)?$/ig)) {
                            interfaceId = key.split('/').pop();
                            if (data.interface_ids.indexOf(interfaceId) == -1) {
                              data.interface_ids.push(interfaceId);
                              data.interfaces[interfaceId] = {
                                interfaceIname: '',
                                DomainName: '',
                                MACAddress: '',
                                Nameservers: [],
                                DHCPEnabled: 0,
                                ipv4: {ids: [], values: []},
                                ipv6: {ids: [], values: []}
                              };
                              data.interfaces[interfaceId].MACAddress =
                                  content.data[key].MACAddress;
                              data.interfaces[interfaceId].DomainName =
                                  content.data[key].DomainName.join(' ');
                              data.interfaces[interfaceId].Nameservers =
                                  content.data[key].Nameservers;
                              data.interfaces[interfaceId].DHCPEnabled =
                                  content.data[key].DHCPEnabled;
                            }
                          } else if (
                              key.match(
                                  /network\/eth\d+(_\d+)?\/ipv[4|6]\/[a-z0-9]+$/ig)) {
                            keyParts = key.split('/');
                            interfaceHash = keyParts.pop();
                            interfaceType = keyParts.pop();
                            interfaceId = keyParts.pop();
  
                            if (data.interfaces[interfaceId][interfaceType]
                                    .ids.indexOf(interfaceHash) == -1) {
                              data.interfaces[interfaceId][interfaceType]
                                  .ids.push(interfaceHash);
                              data.interfaces[interfaceId][interfaceType]
                                  .values.push(content.data[key]);
                              data.ip_addresses[interfaceType].push(
                                  content.data[key]['Address']);
                            }
                          }
                        }
                        return data;
                      }
  
                      if (content.data.hasOwnProperty(
                              '/xyz/openbmc_project/network/config')) {
                        if (content.data['/xyz/openbmc_project/network/config']
                                .hasOwnProperty('HostName')) {
                          hostname =
                              content.data['/xyz/openbmc_project/network/config']
                                  .HostName;
                        }
                        if (content.data['/xyz/openbmc_project/network/config']
                                .hasOwnProperty('DefaultGateway')) {
                          defaultgateway =
                              content.data['/xyz/openbmc_project/network/config']
                                  .DefaultGateway;
                        }
                      }
  
                      if (content.data.hasOwnProperty(
                              '/xyz/openbmc_project/network/eth0') &&
                          content.data['/xyz/openbmc_project/network/eth0']
                              .hasOwnProperty('MACAddress')) {
                        macAddress =
                            content.data['/xyz/openbmc_project/network/eth0']
                                .MACAddress;
                      }
  
                      deferred.resolve({
                        data: content.data,
                        hostname: hostname,
                        defaultgateway: defaultgateway,
                        mac_address: macAddress,
                        formatted_data: parseNetworkData(content)
                      });
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
          setMACAddress: function(interface_name, mac_address) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/' + interface_name +
                         '/attr/MACAddress',
                     withCredentials: true,
                     data: JSON.stringify({'data': mac_address})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setDefaultGateway: function(defaultGateway) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/config/attr/DefaultGateway',
                     withCredentials: true,
                     data: JSON.stringify({'data': defaultGateway})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setDHCPEnabled: function(interfaceName, dhcpEnabled) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/' + interfaceName +
                         '/attr/DHCPEnabled',
                     withCredentials: true,
                     data: JSON.stringify({'data': dhcpEnabled})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setNameservers: function(interfaceName, dnsServers) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/' + interfaceName +
                         '/attr/Nameservers',
                     withCredentials: true,
                     data: JSON.stringify({'data': dnsServers})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          deleteIPV4: function(interfaceName, networkID) {
            return $http({
                     method: 'POST',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/' + interfaceName +
                         '/ipv4/' + networkID + '/action/Delete',
                     withCredentials: true,
                     data: JSON.stringify({'data': []})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          addIPV4: function(
              interfaceName, ipAddress, netmaskPrefixLength, gateway) {
            return $http({
                     method: 'POST',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/' + interfaceName +
                         '/action/IP',
                     withCredentials: true,
                     data: JSON.stringify({
                       'data': [
                         'xyz.openbmc_project.Network.IP.Protocol.IPv4',
                         ipAddress, +netmaskPrefixLength, gateway
                       ]
                     })
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getLEDState: function() {
            var deferred = $q.defer();
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/led/groups/enclosure_identify',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      deferred.resolve(content.data.Asserted);
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
          login: function(username, password, callback) {
            $http({
              method: 'POST',
              url: DataService.getHost() + '/login',
              withCredentials: true,
              data: JSON.stringify({'data': [username, password]})
            })
                .then(
                    function(response) {
                      if (callback) {
                        callback(response.data);
                      }
                    },
                    function(error) {
                      if (callback) {
                        if (error && error.status && error.status == 'error') {
                          callback(error);
                        } else {
                          callback(error, true);
                        }
                      }
                      console.log(error);
                    });
          },
          logout: function(callback) {
            $http({
              method: 'POST',
              url: DataService.getHost() + '/logout',
              withCredentials: true,
              data: JSON.stringify({'data': []})
            })
                .then(
                    function(response) {
                      if (callback) {
                        callback(response.data);
                      }
                    },
                    function(error) {
                      if (callback) {
                        callback(null, error);
                      }
                      console.log(error);
                    });
          },
          getAccountServiceRoles: function() {
            var roles = [];
  
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/redfish/v1/AccountService/Roles',
                     withCredentials: true
                   })
                .then(
                    function(response) {
                      var members = response.data['Members'];
                      angular.forEach(members, function(member) {
                        roles.push(member['@odata.id'].split('/').pop());
                      });
                      return roles;
                    },
                    function(error) {
                      console.log(error);
                    });
          },
          getAllUserAccounts: function() {
            var deferred = $q.defer();
            var promises = [];
            var users = [];
  
            $http({
              method: 'GET',
              url: DataService.getHost() + '/redfish/v1/AccountService/Accounts',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var members = response.data['Members'];
                      angular.forEach(members, function(member) {
                        promises.push(
                            $http({
                              method: 'GET',
                              url: DataService.getHost() + member['@odata.id'],
                              withCredentials: true
                            }).then(function(res) {
                              return res.data;
                            }));
                      });
  
                      $q.all(promises).then(
                          function(results) {
                            deferred.resolve(results);
                          },
                          function(errors) {
                            deferred.reject(errors);
                          });
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
  
          getAllUserAccountProperties: function(callback) {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() + '/redfish/v1/AccountService',
                     withCredentials: true
                   })
                .then(
                    function(response) {
                      return response.data;
                    },
                    function(error) {
                      console.log(error);
                    });
          },
  
          saveUserAccountProperties: function(lockoutduration, lockoutthreshold) {
            var data = {};
            if (lockoutduration != undefined) {
              data['AccountLockoutDuration'] = lockoutduration;
            }
            if (lockoutthreshold != undefined) {
              data['AccountLockoutThreshold'] = lockoutthreshold;
            }
  
            return $http({
              method: 'PATCH',
              url: DataService.getHost() + '/redfish/v1/AccountService',
              withCredentials: true,
              data: data
            });
          },
  
          createUser: function(user, passwd, role, enabled) {
            var data = {};
            data['UserName'] = user;
            data['Password'] = passwd;
            data['RoleId'] = role;
            data['Enabled'] = enabled;
  
            return $http({
              method: 'POST',
              url: DataService.getHost() + '/redfish/v1/AccountService/Accounts',
              withCredentials: true,
              data: data
            });
          },
          updateUser: function(user, newUser, passwd, role, enabled) {
            var data = {};
            if ((newUser !== undefined) && (newUser != null)) {
              data['UserName'] = newUser;
            }
            if ((role !== undefined) && (role != null)) {
              data['RoleId'] = role;
            }
            if ((enabled !== undefined) && (enabled != null)) {
              data['Enabled'] = enabled;
            }
            if ((passwd !== undefined) && (passwd != null)) {
              data['Password'] = passwd;
            }
            return $http({
              method: 'PATCH',
              url: DataService.getHost() +
                  '/redfish/v1/AccountService/Accounts/' + user,
              withCredentials: true,
              data: data
            });
          },
          deleteUser: function(user) {
            return $http({
              method: 'DELETE',
              url: DataService.getHost() +
                  '/redfish/v1/AccountService/Accounts/' + user,
              withCredentials: true,
            });
          },
          chassisPowerOff: function() {
            var deferred = $q.defer();
            $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/state/chassis0/attr/RequestedPowerTransition',
              withCredentials: true,
              data: JSON.stringify(
                  {'data': 'xyz.openbmc_project.State.Chassis.Transition.Off'})
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      deferred.resolve(content.status);
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
          setLEDState: function(state) {
            return $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/led/groups/enclosure_identify/attr/Asserted',
              withCredentials: true,
              data: JSON.stringify({'data': state})
            })
          },
          bmcReboot: function() {
            return $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/state/bmc0/attr/RequestedBMCTransition',
              withCredentials: true,
              data: JSON.stringify(
                  {'data': 'xyz.openbmc_project.State.BMC.Transition.Reboot'})
            });
          },
          getLastRebootTime: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/state/bmc0/attr/LastRebootTime',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          hostPowerOn: function() {
            var deferred = $q.defer();
            $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
              withCredentials: true,
              data: JSON.stringify(
                  {'data': 'xyz.openbmc_project.State.Host.Transition.On'})
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      deferred.resolve(content.status);
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
          hostPowerOff: function() {
            var deferred = $q.defer();
            $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
              withCredentials: true,
              data: JSON.stringify(
                  {'data': 'xyz.openbmc_project.State.Host.Transition.Off'})
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      deferred.resolve(content.status);
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
            return deferred.promise;
          },
          hostReboot: function() {
            var deferred = $q.defer();
            $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/state/host0/attr/RequestedHostTransition',
              withCredentials: true,
              data: JSON.stringify(
                  {'data': 'xyz.openbmc_project.State.Host.Transition.Reboot'})
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      deferred.resolve(content.status);
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
  
            return deferred.promise;
          },
          getLastPowerTime: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/state/chassis0/attr/LastStateChangeTime',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getLogs: function() {
            var deferred = $q.defer();
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/logging/enumerate',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      var dataClone = JSON.parse(JSON.stringify(content.data));
                      var data = [];
                      var severityCode = '';
                      var priority = '';
                      var health = '';
                      var relatedItems = [];
                      var eventID = 'None';
                      var description = 'None';
  
                      for (var key in content.data) {
                        if (content.data.hasOwnProperty(key) &&
                            content.data[key].hasOwnProperty('Id')) {
                          var severityFlags = {
                            low: false,
                            medium: false,
                            high: false
                          };
                          severityCode =
                              content.data[key].Severity.split('.').pop();
                          priority =
                              Constants.SEVERITY_TO_PRIORITY_MAP[severityCode];
                          severityFlags[priority.toLowerCase()] = true;
                          relatedItems = [];
                          content.data[key].associations.forEach(function(item) {
                            relatedItems.push(item[2]);
                          });
  
                          if (content.data[key].hasOwnProperty(['EventID'])) {
                            eventID = content.data[key].EventID;
                          }
  
                          if (content.data[key].hasOwnProperty(['Description'])) {
                            description = content.data[key].Description;
                          }
  
                          data.push(Object.assign(
                              {
                                path: key,
                                copied: false,
                                priority: priority,
                                severity_code: severityCode,
                                severity_flags: severityFlags,
                                additional_data:
                                    content.data[key].AdditionalData.join('\n'),
                                type: content.data[key].Message,
                                selected: false,
                                search_text:
                                    ('#' + content.data[key].Id + ' ' +
                                     severityCode + ' ' +
                                     content.data[key].Message + ' ' +
                                     content.data[key].Severity + ' ' +
                                     content.data[key].AdditionalData.join(' '))
                                        .toLowerCase(),
                                meta: false,
                                confirm: false,
                                related_items: relatedItems,
                                eventID: eventID,
                                description: description,
                                data: {key: key, value: content.data[key]}
                              },
                              content.data[key]));
                        }
                      }
                      deferred.resolve({data: data, original: dataClone});
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
  
            return deferred.promise;
          },
          getAllSensorStatus: function(callback) {
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/sensors/enumerate',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      var dataClone = JSON.parse(JSON.stringify(content.data));
                      var sensorData = [];
                      var severity = {};
                      var title = '';
                      var tempKeyParts = [];
                      var order = 0;
                      var customOrder = 0;
  
                      function getSensorStatus(reading) {
                        var severityFlags = {
                          critical: false,
                          warning: false,
                          normal: false
                        },
                            severityText = '', order = 0;
  
                        if (reading.hasOwnProperty('CriticalLow') &&
                            reading.Value < reading.CriticalLow) {
                          severityFlags.critical = true;
                          severityText = 'critical';
                          order = 2;
                        } else if (
                            reading.hasOwnProperty('CriticalHigh') &&
                            reading.Value > reading.CriticalHigh) {
                          severityFlags.critical = true;
                          severityText = 'critical';
                          order = 2;
                        } else if (
                            reading.hasOwnProperty('CriticalLow') &&
                            reading.hasOwnProperty('WarningLow') &&
                            reading.Value >= reading.CriticalLow &&
                            reading.Value <= reading.WarningLow) {
                          severityFlags.warning = true;
                          severityText = 'warning';
                          order = 1;
                        } else if (
                            reading.hasOwnProperty('WarningHigh') &&
                            reading.hasOwnProperty('CriticalHigh') &&
                            reading.Value >= reading.WarningHigh &&
                            reading.Value <= reading.CriticalHigh) {
                          severityFlags.warning = true;
                          severityText = 'warning';
                          order = 1;
                        } else {
                          severityFlags.normal = true;
                          severityText = 'normal';
                        }
                        return {
                          flags: severityFlags,
                          severityText: severityText,
                          order: order
                        };
                      }
  
                      for (var key in content.data) {
                        if (content.data.hasOwnProperty(key) &&
                            content.data[key].hasOwnProperty('Unit')) {
                          severity = getSensorStatus(content.data[key]);
  
                          if (!content.data[key].hasOwnProperty('CriticalLow')) {
                            content.data[key].CriticalLow = '--';
                            content.data[key].CriticalHigh = '--';
                          }
  
                          if (!content.data[key].hasOwnProperty('WarningLow')) {
                            content.data[key].WarningLow = '--';
                            content.data[key].WarningHigh = '--';
                          }
  
                          tempKeyParts = key.split('/');
                          title = tempKeyParts.pop();
                          title = tempKeyParts.pop() + '_' + title;
                          title = title.split('_')
                                      .map(function(item) {
                                        return item.toLowerCase()
                                                   .charAt(0)
                                                   .toUpperCase() +
                                            item.slice(1);
                                      })
                                      .reduce(function(prev, el) {
                                        return prev + ' ' + el;
                                      });
  
                          content.data[key].Value = getScaledValue(
                              content.data[key].Value, content.data[key].Scale);
                          content.data[key].CriticalLow = getScaledValue(
                              content.data[key].CriticalLow,
                              content.data[key].Scale);
                          content.data[key].CriticalHigh = getScaledValue(
                              content.data[key].CriticalHigh,
                              content.data[key].Scale);
                          content.data[key].WarningLow = getScaledValue(
                              content.data[key].WarningLow,
                              content.data[key].Scale);
                          content.data[key].WarningHigh = getScaledValue(
                              content.data[key].WarningHigh,
                              content.data[key].Scale);
                          if (Constants.SENSOR_SORT_ORDER.indexOf(
                                  content.data[key].Unit) > -1) {
                            customOrder = Constants.SENSOR_SORT_ORDER.indexOf(
                                content.data[key].Unit);
                          } else {
                            customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
                          }
  
                          sensorData.push(Object.assign(
                              {
                                path: key,
                                selected: false,
                                confirm: false,
                                copied: false,
                                title: title,
                                unit:
                                    Constants
                                        .SENSOR_UNIT_MAP[content.data[key].Unit],
                                severity_flags: severity.flags,
                                status: severity.severityText,
                                order: severity.order,
                                custom_order: customOrder,
                                search_text:
                                    (title + ' ' + content.data[key].Value + ' ' +
                                     Constants.SENSOR_UNIT_MAP[content.data[key]
                                                                   .Unit] +
                                     ' ' + severity.severityText + ' ' +
                                     content.data[key].CriticalLow + ' ' +
                                     content.data[key].CriticalHigh + ' ' +
                                     content.data[key].WarningLow + ' ' +
                                     content.data[key].WarningHigh + ' ')
                                        .toLowerCase(),
                                original_data:
                                    {key: key, value: content.data[key]}
                              },
                              content.data[key]));
                        }
                      }
  
                      sensorData.sort(function(a, b) {
                        return a.title.localeCompare(
                            b.title, 'en', {numeric: true});
                      });
  
                      callback(sensorData, dataClone);
                    },
                    function(error) {
                      console.log(error);
                    });
          },
          getActivation: function(imageId) {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/software/' + imageId +
                         '/attr/Activation',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getFirmwares: function() {
            var deferred = $q.defer();
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/software/enumerate',
              withCredentials: true
            })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
                      var data = [];
                      var isExtended = false;
                      var bmcActiveVersion = '';
                      var hostActiveVersion = '';
                      var imageType = '';
                      var extendedVersions = [];
                      var functionalImages = [];
  
                      function getFormatedExtendedVersions(extendedVersion) {
                        var versions = [];
                        extendedVersion = extendedVersion.split(',');
  
                        extendedVersion.forEach(function(item) {
                          var parts = item.split('-');
                          var numberIndex = 0;
                          for (var i = 0; i < parts.length; i++) {
                            if (/[0-9]/.test(parts[i])) {
                              numberIndex = i;
                              break;
                            }
                          }
                          var titlePart = parts.splice(0, numberIndex);
                          titlePart = titlePart.join('');
                          titlePart = titlePart[0].toUpperCase() +
                              titlePart.substr(1, titlePart.length);
                          var versionPart = parts.join('-');
                          versions.push({title: titlePart, version: versionPart});
                        });
  
                        return versions;
                      }
  
                      // Get the list of functional images so we can compare
                      // later if an image is functional
                      if (content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]) {
                        functionalImages =
                            content.data[Constants.FIRMWARE.FUNCTIONAL_OBJPATH]
                                .endpoints;
                      }
                      for (var key in content.data) {
                        if (content.data.hasOwnProperty(key) &&
                            content.data[key].hasOwnProperty('Version')) {
                          var activationStatus = '';
  
                          // If the image is "Functional" use that for the
                          // activation status, else use the value of
                          // "Activation"
                          // github.com/openbmc/phosphor-dbus-interfaces/blob/master/xyz/openbmc_project/Software/Activation.interface.yaml
                          if (content.data[key].Activation) {
                            activationStatus =
                                content.data[key].Activation.split('.').pop();
                          }
  
                          if (functionalImages.includes(key)) {
                            activationStatus = 'Functional';
                          }
  
                          imageType = content.data[key].Purpose.split('.').pop();
                          isExtended = content.data[key].hasOwnProperty(
                                           'ExtendedVersion') &&
                              content.data[key].ExtendedVersion != '';
                          if (isExtended) {
                            extendedVersions = getFormatedExtendedVersions(
                                content.data[key].ExtendedVersion);
                          }
                          data.push(Object.assign(
                              {
                                path: key,
                                activationStatus: activationStatus,
                                imageId: key.split('/').pop(),
                                imageType: imageType,
                                isExtended: isExtended,
                                extended:
                                    {show: false, versions: extendedVersions},
                                data: {key: key, value: content.data[key]}
                              },
                              content.data[key]));
  
                          if (activationStatus == 'Functional' &&
                              imageType == 'BMC') {
                            bmcActiveVersion = content.data[key].Version;
                          }
  
                          if (activationStatus == 'Functional' &&
                              imageType == 'Host') {
                            hostActiveVersion = content.data[key].Version;
                          }
                        }
                      }
  
                      deferred.resolve({
                        data: data,
                        bmcActiveVersion: bmcActiveVersion,
                        hostActiveVersion: hostActiveVersion
                      });
                    },
                    function(error) {
                      console.log(error);
                      deferred.reject(error);
                    });
  
            return deferred.promise;
          },
          changePriority: function(imageId, priority) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/software/' + imageId +
                         '/attr/Priority',
                     withCredentials: true,
                     data: JSON.stringify({'data': priority})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          deleteImage: function(imageId) {
            return $http({
                     method: 'POST',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/software/' + imageId +
                         '/action/Delete',
                     withCredentials: true,
                     data: JSON.stringify({'data': []})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          activateImage: function(imageId) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/software/' + imageId +
                         '/attr/RequestedActivation',
                     withCredentials: true,
                     data: JSON.stringify(
                         {'data': Constants.FIRMWARE.ACTIVATE_FIRMWARE})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          uploadImage: function(file) {
            return $http({
                     method: 'POST',
                     timeout: 5 * 60 * 1000,
                     url: DataService.getHost() + '/upload/image',
                     // Overwrite the default 'application/json' Content-Type
                     headers: {'Content-Type': 'application/octet-stream'},
                     withCredentials: true,
                     data: file
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          downloadImage: function(host, filename) {
            return $http({
                     method: 'POST',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/software/action/DownloadViaTFTP',
                     withCredentials: true,
                     data: JSON.stringify({'data': [filename, host]}),
                     responseType: 'arraybuffer'
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getServerInfo: function() {
            // TODO: openbmc/openbmc#3117 Need a way via REST to get
            // interfaces so we can get the system object(s) by the looking
            // for the system interface.
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/inventory/system',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getBMCTime: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() + '/xyz/openbmc_project/time/bmc',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getTime: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/time/enumerate',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          // Even though NTPServers is a network interface specific path
          // (e.g. /xyz/openbmc_project/network/eth0/attr/NTPServers) it acts
          // like a global setting. Just use eth0 for setting and getting the
          // NTP Servers until it is moved to a non-network interface specific
          // path like it is in Redfish. TODO: openbmc/phosphor-time-manager#4
          getNTPServers: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/eth0/attr/NTPServers',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setNTPServers: function(ntpServers) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/eth0/attr/NTPServers',
                     withCredentials: true,
                     data: JSON.stringify({'data': ntpServers})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setTimeMode: function(timeMode) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/time/sync_method/attr/TimeSyncMethod',
                     withCredentials: true,
                     data: JSON.stringify({'data': timeMode})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setTimeOwner: function(timeOwner) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/time/owner/attr/TimeOwner',
                     withCredentials: true,
                     data: JSON.stringify({'data': timeOwner})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setBMCTime: function(time) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/time/bmc/attr/Elapsed',
                     withCredentials: true,
                     data: JSON.stringify({'data': time})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setHostTime: function(time) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/time/host/attr/Elapsed',
                     withCredentials: true,
                     data: JSON.stringify({'data': time})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          getHardwares: function(callback) {
            $http({
              method: 'GET',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/inventory/enumerate',
              withCredentials: true
            }).then(function(response) {
              var json = JSON.stringify(response.data);
              var content = JSON.parse(json);
              var hardwareData = [];
              var keyIndexMap = {};
              var title = '';
              var depth = '';
              var data = [];
              var searchText = '';
              var componentIndex = -1;
              var parent = '';
  
              function isSubComponent(key) {
                for (var i = 0; i < Constants.HARDWARE.parent_components.length;
                     i++) {
                  if (key.split(Constants.HARDWARE.parent_components[i]).length ==
                      2)
                    return true;
                }
  
                return false;
              }
  
              function titlelize(title) {
                title = title.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
                for (var i = 0; i < Constants.HARDWARE.uppercase_titles.length;
                     i++) {
                  if (title.toLowerCase().indexOf(
                          (Constants.HARDWARE.uppercase_titles[i] + ' ')) > -1) {
                    return title.toUpperCase();
                  }
                }
  
                return title;
              }
  
              function camelcaseToLabel(obj) {
                var transformed = [], label = '', value = '';
                for (var key in obj) {
                  label = key.replace(/([A-Z0-9]+)/g, ' $1').replace(/^\s+/, '');
                  if (obj[key] !== '') {
                    value = obj[key];
                    if (value == 1 || value == 0) {
                      value = (value == 1) ? 'Yes' : 'No';
                    }
                    transformed.push({key: label, value: value});
                  }
                }
  
                return transformed;
              }
  
              function determineParent(key) {
                var levels = key.split('/');
                levels.pop();
                return levels.join('/');
              }
  
              function getSearchText(data) {
                var searchText = '';
                for (var i = 0; i < data.length; i++) {
                  searchText += ' ' + data[i].key + ' ' + data[i].value;
                }
  
                return searchText;
              }
  
              for (var key in content.data) {
                if (content.data.hasOwnProperty(key) &&
                    key.indexOf(Constants.HARDWARE.component_key_filter) == 0) {
                  data = camelcaseToLabel(content.data[key]);
                  searchText = getSearchText(data);
                  title = key.split('/').pop();
                  // All and only associations have the property "endpoints".
                  // We don't want to show associations on the hardware page.
                  // Example: An association from the BMC inventory item to the
                  // BMC firmware images.
                  if (content.data[key].hasOwnProperty('endpoints')) {
                    continue;
                  }
  
                  title = titlelize(title);
                  // e.g. /xyz/openbmc_project/inventory/system and
                  // /xyz/openbmc_project/inventory/system/chassis are depths of 5
                  // and 6.
                  depth = key.split('/').length;
                  parent = determineParent(key);
  
                  if (!isSubComponent(key)) {
                    hardwareData.push(Object.assign(
                        {
                          path: key,
                          title: title,
                          depth: depth,
                          parent: parent,
                          selected: false,
                          expanded: false,
                          search_text: title.toLowerCase() + ' ' +
                              searchText.toLowerCase(),
                          sub_components: [],
                          original_data: {key: key, value: content.data[key]}
                        },
                        {items: data}));
  
                    keyIndexMap[key] = hardwareData.length - 1;
                  } else {
                    parent = determineParent(key)
                    componentIndex = keyIndexMap[parent];
                    data = content.data[key];
                    data.title = title;
                    hardwareData[componentIndex].sub_components.push(data);
                    hardwareData[componentIndex].search_text +=
                        ' ' + title.toLowerCase();
  
                    // Sort the subcomponents alphanumeric so they are displayed
                    // on the inventory page in order (e.g. core 0, core 1, core
                    // 2, ... core 12, core 13)
                    hardwareData[componentIndex].sub_components.sort(function(
                        a, b) {
                      return a.title.localeCompare(
                          b.title, 'en', {numeric: true});
                    });
                  }
                }
              }
              // First, order the components by depth and then place the child
              // components beneath their parent component alphanumerically. Can
              // be removed with completion of
              // https://github.com/openbmc/openbmc/issues/3401
              // TODO: Remove this once implemented in back end
              hardwareData.sort(function(a, b) {
                if (a.depth < b.depth) return -1;
                if (a.depth > b.depth) return 1;
                return b.title.localeCompare(a.title, 'en', {numeric: true});
              });
  
              var orderedComponents = [];
  
              for (var i = 0; i < hardwareData.length; i++) {
                if (!keyIndexMap[hardwareData[i].parent]) {
                  orderedComponents.push(hardwareData[i]);
                } else {
                  for (var j = 0; j < orderedComponents.length; j++) {
                    if (orderedComponents[j].path === hardwareData[i].parent) {
                      var child = hardwareData[i];
                      orderedComponents.splice(j + 1, 0, child);
                    }
                  }
                }
              }
  
              if (callback) {
                callback(orderedComponents, content.data);
              } else {
                return {data: orderedComponents, original_data: content.data};
              }
            });
          },
          deleteLogs: function(logs) {
            var defer = $q.defer();
            var promises = [];
  
            function finished() {
              defer.resolve();
            }
  
            logs.forEach(function(item) {
              promises.push($http({
                method: 'POST',
                url: DataService.getHost() +
                    '/xyz/openbmc_project/logging/entry/' + item.Id +
                    '/action/Delete',
                withCredentials: true,
                data: JSON.stringify({'data': []})
              }));
            });
  
            $q.all(promises).then(finished);
  
            return defer.promise;
          },
          resolveLogs: function(logs) {
            var promises = [];
  
            logs.forEach(function(item) {
              promises.push($http({
                method: 'PUT',
                url: DataService.getHost() +
                    '/xyz/openbmc_project/logging/entry/' + item.Id +
                    '/attr/Resolved',
                withCredentials: true,
                data: JSON.stringify({'data': true})
              }));
            });
            return $q.all(promises);
          },
          setRemoteLoggingServer: (data) => {
            const ip = data.hostname;
            const port = data.port;
            const setIPRequest = $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/logging/config/remote/attr/Address',
              withCredentials: true,
              data: {'data': ip}
            });
            const setPortRequest = $http({
              method: 'PUT',
              url: DataService.getHost() +
                  '/xyz/openbmc_project/logging/config/remote/attr/Port',
              withCredentials: true,
              data: {'data': port}
            });
            const promises = [setIPRequest, setPortRequest];
            return $q.all(promises);
          },
          getRemoteLoggingServer: () => {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/logging/config/remote',
                     withCredentials: true
                   })
                .then((response) => {
                  const remoteServer = response.data.data;
                  if (remoteServer === undefined) {
                    return undefined;
                  }
                  const hostname = remoteServer.Address;
                  const port = remoteServer.Port;
                  if (hostname === '') {
                    return undefined;
                  } else {
                    return {
                      hostname, port
                    }
                  }
                });
          },
          disableRemoteLoggingServer: () => {
            return SERVICE.setRemoteLoggingServer({hostname: '', port: 0});
          },
          updateRemoteLoggingServer: (data) => {
            // Recommended to disable existing configuration
            // before updating config to new server
            // https://github.com/openbmc/phosphor-logging#changing-the-rsyslog-server
            return SERVICE.disableRemoteLoggingServer()
                .then(() => {
                  return SERVICE.setRemoteLoggingServer(data);
                })
                .catch(() => {
                  // try updating server even if initial disable attempt fails
                  return SERVICE.setRemoteLoggingServer(data);
                });
          },
          getPowerConsumption: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/sensors/power/total_power',
                     withCredentials: true
                   })
                .then(
                    function(response) {
                      var json = JSON.stringify(response.data);
                      var content = JSON.parse(json);
  
                      return getScaledValue(
                                 content.data.Value, content.data.Scale) +
                          ' ' +
                          Constants.POWER_CONSUMPTION_TEXT[content.data.Unit];
                    },
                    function(error) {
                      if ('Not Found' == error.statusText) {
                        return Constants.POWER_CONSUMPTION_TEXT.notavailable;
                      } else {
                        throw error;
                      }
                    });
          },
          getPowerCap: function() {
            return $http({
                     method: 'GET',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/control/host0/power_cap',
                     withCredentials: true
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setPowerCapEnable: function(powerCapEnable) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCapEnable',
                     withCredentials: true,
                     data: JSON.stringify({'data': powerCapEnable})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setPowerCap: function(powerCap) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/control/host0/power_cap/attr/PowerCap',
                     withCredentials: true,
                     data: JSON.stringify({'data': powerCap})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
          setHostname: function(hostname) {
            return $http({
                     method: 'PUT',
                     url: DataService.getHost() +
                         '/xyz/openbmc_project/network/config/attr/HostName',
                     withCredentials: true,
                     data: JSON.stringify({'data': hostname})
                   })
                .then(function(response) {
                  return response.data;
                });
          },
        };
        return SERVICE;
      }
    ]);
  })(window.angular);
  