text: angular.module("skypeapp.services", [])
  .factory("skypeSvc", ["$rootScope", "$http", "$q", function($rootScope, $http, $q) {
      var skypeSvc = {};
      
      //private properties
      var apiManager = null;
      var client = null;
      
      skypeSvc.config = {
          version: "sdk-samples/1.0.0", // this helps to identify telemetry generated by the samples
          apiKey: "a42fcebd-5b43-4b89-a065-74450fb91255", // SDK DF
          apiKeyCC: "9c967f6b-a846-4df2-b43d-5167e47d81e1", // SDK+CC DF
          client_id: "6fd45769-7a1e-4dc5-a876-90fa781b3d3e",
          authLink: "https://login.windows.net/common/oauth2/authorize?response_type=token",
          authResource: "https://webdir.online.lync.com",
          redirect: "http://localhost:59915",
          
          auth: null,
          origins: ["https://webdir.online.lync.com/autodiscover/autodiscoverservice.svc/root"],
          cors: true,
          redirect_uri: "/auth.html"
      };
      
      //ensures the skype client object is initialized
      var ensureClient = function() {
          var deferred = $q.defer();
          
          if (client != null)
              deferred.resolve();
          else {
              Skype.initialize({
                  apiKey: skypeSvc.config.apiKey
              }, function (api) {
                  apiManager = api;
                  client = apiManager.application();
                  client.signInManager.state.changed(function (state) {
                      $rootScope.$broadcast("stateChanged", state);
                  });
                  deferred.resolve();
              }, function (er) {
                  deferred.resolve(er);
              });
          }
          
          return deferred.promise;
      };
      
      //signs into skype
      skypeSvc.signIn = function() {
          var deferred = $q.defer();
          
          ensureClient().then(function() {
              //determine if the user is already signed in or not
              if (client.signInManager.state() == "SignedOut") {
                  client.signInManager.signIn(skypeSvc.config).then(function (z) {
                      //listen for status changes
                      client.personsAndGroupsManager.mePerson.status.changed(function (newStatus) {
                          console.log("logged in status: " + newStatus);                
                      });
                      
                      //In the future we can listen for new "inbound" conversations
                      client.conversationsManager.conversations.added(function (conversation) { });
  
                      //resolve the promise
                      deferred.resolve();
                  }, function (er) {
                      deferred.reject(er);
                  });
              }
              else {
                  //resolve the promise
                  deferred.resolve();
              }
          }, function(er) {
              deferred.reject(er);
          });
          
          return deferred.promise;
      }
      
      //get the users contacts
      skypeSvc.getContacts = function() {
          var deferred = $q.defer();
          
          ensureClient().then(function() {
              client.personsAndGroupsManager.all.persons.get().then(function (persons) {
                  //parse contacts into clean array
                  var contacts = [];
                  persons.forEach(function (person) {
                      contacts.push({
                          name: person.displayName(),
                          sip: person.id(),
                          person: person,
                          status: "Offline",
                          conversation: []
                      });
                  });
                  deferred.resolve(contacts);
              });
          }, function (er) {
              deferred.reject(err);
          });
          
          return deferred.promise;  
      };
      
      skypeSvc.sendMessage = function(person, text) {
          var deferred = $q.defer();
          
          //get the conversation for the person
          var conversation = client.conversationsManager.getConversation(person);
          var chatService = conversation.chatService;
          
          //check if we already have chat going
          if (!conversation.activeModalities.chat()) {
              conversation.selfParticipant.chat.state.when("Connected", function () {
                  var history = conversation.historyService;
                  if (history.activityItems) {
                      //listen for new messages on the conversation
                      history.activityItems.added(function(item) {
                          if (item.type() === "TextMessage") {
                              //check direction of message
                              if (item.direction() === "Incoming") {
                                  console.log("received a text message: ", item.text());
                                  $rootScope.$broadcast("messageRecieved", item);
                              }
                              else if (item.direction() === "Outgoing") {
                                  console.log("sent a text message: ", item.text());
                                  deferred.resolve();
                              }
                          } 
                      });
                  }
              });
          }
          else
              deferred.resolve();
          chatService.sendMessage(text);
          
          return deferred.promise;
      };
      
      skypeSvc.getProfilePic = function() {
          var deferred = $q.defer();
          
          $http.get("https://graph.microsoft.com/v1.0/me/photo/$value", { responseType: "blob" }).then(function (image) {
              // Convert blob into image that app can display
              var imgUrl = window.URL || window.webkitURL;
              var blobUrl = imgUrl.createObjectURL(image.data);
              deferred.resolve(blobUrl);
          }, function (err) {
              // Error calling API...reject the promise
              deferred.reject("Image failed to load");
          });
          
          return deferred.promise;
      };
      
      return skypeSvc;
  }]);
  
  angular.module("skypeapp.controllers", [])
  .controller("loginCtrl", ["$scope", "$location", "adalAuthenticationService", function($scope, $location, adalSvc) {
      if (adalSvc.userInfo.isAuthenticated) {
          $location.path("/skype");
      }
          
      $scope.login = function() {
          adalSvc.login();  
      };
  }])
  .controller("skypeCtrl", ["$scope", "skypeSvc", function($scope, skypeSvc) {
      $scope.me = { name: "", email: "", status: "" };
      
      //load the users profile pic
      $scope.pic = "/content/nopic.jpg"
      skypeSvc.getProfilePic().then(function(img) {
          $scope.pic = img; 
      });
      
      //sign into skype
      skypeSvc.signIn().then(function() {
          console.log("signed in");
          
          //load contacts
          skypeSvc.getContacts().then(function(contacts) {
              $scope.contacts = contacts;
              angular.forEach($scope.contacts, function(e, i) {
                  e.person.status.get().then(function (s) {
                      toggleStatus(e, s);
                  });
                  
                  e.person.status.changed(function (s) {
                      toggleStatus(e, s);
                  });
                  
                  e.person.status.subscribe();
              });
          }, function(err) {
              console.log("error: " + er);    
          });
      }, function(er) {
          console.log("error: " + er);
      });
      
      var toggleStatus = function(contact, status) {
          contact.status = status;
          if ($scope.activeContact) {
              if (contact.sip == $scope.activeContact.sip)
                  $scope.chatDisabled = !canChat(contact);
          }
          
          if (!$scope.$$phase)
              $scope.$apply();
      };
      
      //set a contact as active
      $scope.setActive = function(contact) {
          angular.forEach($scope.contacts, function(e, i) {
              e.active = false; 
          });
          contact.active = true;
          $scope.activeContact = contact;
          $scope.chatDisabled = !canChat($scope.activeContact);
      };
      
      //handles key pressed events for sending messages
      $scope.keyPressed = function() {
          if (event.keyCode == 13)
              $scope.sendMessage();
      };
      
      var canChat = function(contact) {
          var chattableStatus = { 
              Online: true, Busy: true, Idle: true, IdleOnline: true, Away: true, BeRightBack: true,
              DoNotDisturb: false, Offline: false, Unknown: false, Hidden: false };
          return chattableStatus[contact.status];
      };
      
      //sends message to activeContact
      $scope.sendMessage = function() {
          if (canChat($scope.activeContact)) {
              //sent the message and wait for response
              skypeSvc.sendMessage($scope.activeContact.person, $scope.message).then(function() {
                  $scope.activeContact.conversation.unshift({ text: $scope.message, me: true, sender: "Me" });
                  $scope.message = "";
              }); 
          }
      };
      
      //listen for messages broadcast from the skypeSvc
      $scope.$on("messageRecieved", function(evt, val) {
          //find the sender
          var senderSip = val.sender.id();
          var contact = null;
          
          //find the contact this conversation is related to
          angular.forEach($scope.contacts, function(e, i) {
              if (e.sip === senderSip) {
                  contact = e;
              }
          });
          if (contact) {
              contact.conversation.unshift({ text: val.text(), me: false, sender: val.sender.displayName() });
              if (!$scope.$$phase)
                  $scope.$apply();
          }
      });
      
      //listen for skype state changes
      $scope.$on("stateChanged", function (evt, val) {
          $scope.state = val;
      });
  }]);
  
  angular.module("skypeapp", ["skypeapp.services", "skypeapp.controllers", "ngRoute", "AdalAngular"])
  .config(["$routeProvider", "$httpProvider", "adalAuthenticationServiceProvider", function($routeProvider, $httpProvider, adalProvider) {
      $routeProvider.when("/login", {
          controller: "loginCtrl",
          templateUrl: "/app/templates/view-login.html",
          requireADLogin: false
      }).when ("/skype", {
          controller: "skypeCtrl",
          templateUrl: "/app/templates/view-skype.html",
          requireADLogin: true
      }).otherwise({
          redirectTo: "/login"
      });
      
      adalProvider.init({
          instance: "https://login.microsoftonline.com/",
          tenant: "rzdemos.com",
          clientId: "6fd45769-7a1e-4dc5-a876-90fa781b3d3e",
          endpoints: {
              "https://webdir.online.lync.com": "https://webdir.online.lync.com",
              "https://graph.microsoft.com": "https://graph.microsoft.com"
          }
      }, $httpProvider);
  }]);