app.controller('MainCtrl', [
'$rootScope', '$scope', '$routeParams', '$location', '$timeout', '$q',
function($rootScope, $scope, $routeParams, $location, $timeout, $q) {
  'use strict';

  var model = $scope.model = {};

  model.cardPictureFile = '';
  model.cardPicture = '';

  model.imageData = '';
  model.imageFilename = 'bizcardmaker-com';
  model.imageExt = '.jpg';

  model.pdfData = '';
  model.pdfFilename = 'bizcardmaker-com.pdf';

  model.loadingCard = false;

  var expire = new Date();
  expire.setDate(expire.getDate() + 23);
  model.promoExpire = expire;

  model.storeDefaults = {
    card: {
      name: 'John Doe',
      position: 'Position',
      organization: 'Organization',
      location: 'City, State',
      phone: '(123) 555-1234',
      email: 'john.doe@cmail.com',
      url: 'www.john-doe.com'
    },
    position: {
      picture: {},
      person: {},
      details: {},
      email: {},
      url: {}
    }
  };

  model.store = {
    card: {},
    position: {}
  };

  angular.copy(model.storeDefaults, model.store);

  var storedDetails = window.localStorage.getItem('bizcardmaker-store');

  if(storedDetails) {
    angular.extend(model.store, angular.fromJson(storedDetails));
  }

  // Remy Sharp's debounce
  // https://remysharp.com/2010/07/21/throttling-function-calls
  var debounce = function(fn, delay) {
    var timer = null;
    return function () {
      var context = this, args = arguments;
      clearTimeout(timer);
      timer = setTimeout(function () {
        fn.apply(context, args);
      }, delay);
    };
  };

  // save edits to localstorage
  $scope.$watch('model.store', debounce(function(store) {

    window.localStorage.setItem('bizcardmaker-store', angular.toJson(store));

  }, 500), true);

  var clearInlineStyles = function() {
    if (!document.querySelector('.card-preview')) {
      return;
    }

    // clear all inline styles
    // generated by editor and draggable
    var cardChildren = document.querySelector('.card-preview').querySelectorAll('*');
    angular.forEach(cardChildren, function(c) {
      c.removeAttribute('style');
    });
  };

  // reset all saved data
  $scope.ResetCard = function(change) {

    clearInlineStyles();

    if(change) {

      // on change, only reset the positions
      angular.copy(model.storeDefaults.position, model.store.position);

    } else {

      // complete reset
      var previousTheme = model.store.theme;

      angular.copy(model.storeDefaults, model.store);

      // don't reset the currently selected theme
      model.store.theme = previousTheme;
    }


    window.localStorage.removeItem('bizcardmaker-store');

  };

  // if we have a stored theme
  // set it as active.
  if (model.store.theme) {
    $location.search('theme', model.store.theme);
  }

  $scope.$on('$locationChangeStart', function(){
    var theme = $location.search().theme;

    // reset card styles when changing themes
    // except the text data
    if(theme !== model.store.theme) {
      $scope.ResetCard(true);
    }

    model.store.theme = theme;
  });

  $scope.$watch('model.cardPictureFile', function() {

    if(model.cardPictureFile) {

      var imageType = /image.*/;

      if (model.cardPictureFile.type.match(imageType)) {
        var reader = new FileReader();

        reader.onload = function() {

          $timeout(function() {
            model.cardPicture = reader.result;
          });

        };

        reader.readAsDataURL(model.cardPictureFile);

      } else {

        window.alert('File not supported!');

      }

    }

  });

  /* Turn px values into em
   */
  var pxToEm = function(elem) {

    var parentStyle = window.getComputedStyle(elem.parentNode, null);
    var style = window.getComputedStyle(elem, null);
    var childFontSize = parseFloat(style.fontSize);
    var parentFontSize = parseFloat(parentStyle.fontSize);

    var properties = [ 'left', 'top', 'width', 'height' ];
    var inlineStyleValue = '';

    var newValues = {};

    properties.forEach(function(prop) {

      inlineStyleValue = elem.style[prop];

      // only if the property is set as inline style
      if(inlineStyleValue && inlineStyleValue.indexOf('em') === -1) {

        // var childValue = parseFloat(style[prop]);
        var childValue = parseFloat(style[prop]);
        var newValue = childValue / parentFontSize;

        // recalculate depending on element fontSize
        // since it influences ems
        var emSize = childFontSize / parentFontSize;
        newValue += (newValue - newValue * emSize) / emSize;

        //elem.style[prop] = newValue + 'em';
        newValues[prop] = newValue + 'em';

      }

    });

    // change all values at the same time, for performance
    Object.keys(newValues).forEach(function(key) {
      elem.style[key] = newValues[key];
    });

    // convert fontSize to em, only for font tags
    if(elem.tagName.toLowerCase() === 'font' && style.fontSize.indexOf('em') === -1) {
      elem.style.fontSize = childFontSize / parentFontSize + 'em';
    }

  };

  var fontSizes = {
    '1': '10',
    '2': '13',
    '3': '16',
    '4': '18',
    '5': '24',
    '6': '32',
    '7': '48'
  };

  // replace px styles and font sizes generated by the editor
  // so that I can later enlarge the entire business card with ems
  var fixPxSizes = function(container) {
    var editors = container.querySelectorAll('[contenteditable]');

    var children;

    angular.forEach(editors, function(e) {
      children = e.querySelectorAll('*');
      angular.forEach(children, function(c) {
        // first turn font size=x to px
        if(c.tagName.toLowerCase() === 'font') {
          c.style.fontSize = fontSizes[c.size] + 'px';
        }

        pxToEm(c);
      });
    });

    // fix dragged positions
    var lists = container.querySelectorAll('.card-item[style]');
    var picture = container.querySelector('.card-picture[style]');

    angular.forEach(lists, function(li) {
      pxToEm(li);
    });

    if(picture) {
      pxToEm(picture);
    }

  };

  // place business card on a canvas
  $scope.generatePicture = function(cb) {
    cb = cb || function() {};

    var deferred = $q.defer();

    // remove text selection, to hide still-open editors
    window.getSelection().removeAllRanges();

    var $cardClone = document.querySelector('.js-card-container').cloneNode(true);
    $cardClone.classList.add('card-invisible');

    // add the card to the dom before converting to em
    // so we can getComputedStyle
    document.body.appendChild($cardClone);

    // before generation, turn all px values to em for up-scaling
    fixPxSizes($cardClone);

    // double it up only after the px->em conversion
    $cardClone.classList.add('card-big');

    model.loadingCard = true;

    html2canvas($cardClone, {
      letterRendering: true
    })
    .then(function(canvas) {
      document.body.removeChild($cardClone);
      model.loadingCard = false;

      deferred.resolve(canvas);

      // callback for Karma
      cb(canvas);
    });

    return deferred.promise;

  };

  $scope.DownloadPdf = function() {
    $scope.generatePicture()
    .then(function(canvas) {
      var imgData = canvas.toDataURL('image/jpeg', 1.0);
      window.GeneratePdf(model.pdfFilename, imgData);
    });
  };

  $scope.DownloadPicture = function() {

    $scope.generatePicture()
    .then(function(canvas) {

      // make the canvas a blob, so we can download it with downloadify
      canvas.toBlob(
        function (blob) {

          var filename = model.imageFilename + '-' + model.store.theme + model.imageExt;

          // saveAs is global from FileSaver.js
          // FileSaver is included in jsPdf
          saveAs(blob, filename);

          // scroll back to the card
          // since saveAs scrolls to the top
          var $cardContainer = $('.card-container');
          $cardContainer[0].scrollIntoView(true);

        },
        'image/jpeg'
      );

    });
  };

  var allTemplates = 1;
  var loadedTemplates = 0;
  $scope.$on('$includeContentLoaded', function() {
    // when loading all the includes
    loadedTemplates++;
    if (loadedTemplates !== allTemplates) {
      return;
    }

    // init foundation plugins - modal and dropdown
    $(document.querySelector('.card-editor')).foundation();

    // hack to prevent automatic scrolling from contenteditable
    var $cardContent = document.querySelector('.card-content');
    if($cardContent) {
      /* Feature detection */
      var passiveSupported = false;
      try {
        window.addEventListener('test', null, Object.defineProperty({}, 'passive', { get: function() { passiveSupported = true; } }));
      } catch(err) {}

      $cardContent.addEventListener('scroll', function(event) {
        $cardContent.scrollTop = 0;
        $cardContent.scrollLeft = 0;
      }, passiveSupported ? {passive: true} : true);
    }

  });

}]);
