var parseFiles = function(files, cb) {
  var cnt = 0;
  var txts = [];
  var onload = function(res) {
    var txt = res.target.result;
    txts.push(txt.split(',')[1]);
    cnt--;
    if (!cnt) {
      cb(txts);
    }
  };
  _.each(files, function(file) {
    cnt++;
    console.log('starting file reader');
    var reader = new FileReader();
    reader.onload = onload;
    reader.onerror = function(err) {
      // return error
      // TODO: find a better way to propogate error upstream
      console.log('got back error', err);
      cb([]);
    };
    reader.readAsDataURL(file);
  });
};

angular
.module('webui.ctrls.modal', [
  "ui.bootstrap", 'webui.services.deps', 'webui.services.modals', 'webui.services.rpc',
  'webui.services.configuration'
])
.controller('ModalCtrl', [
  '$_', '$scope', '$modal', "$modals", '$rpc','$fileSettings', '$downloadProps',
  function(_, scope, $modal, modals, rpc, fsettings, dprops) {

  scope.getUris = {
    open: function(cb) {
      var self = this;
      this.uris = "";
      this.downloadSettingsCollapsed = true;
      this.advancedSettingsCollapsed = true;
      this.settings = {};
      this.fsettings = _.cloneDeep(fsettings);
      this.cb = cb;

      // fill in default download properties
      _.forEach(dprops, function(p) {
        self.settings[p] = self.fsettings[p];
        delete self.fsettings[p];
      });

      this.inst = $modal.open({
        templateUrl: "getUris.html",
        scope: scope,
        windowClass: "modal-large"
      });
      this.inst.result.then(function() {
        delete self.inst;
        if (self.cb) {
          var settings = {};
          // no need to send in default values, just the changed ones
          for (var i in self.settings) {
            if (fsettings[i].val != self.settings[i].val)
                settings[i] = self.settings[i].val;
          }
          for (var i in self.fsettings) {
            if (fsettings[i].val != self.fsettings[i].val)
                settings[i] = self.fsettings[i].val;
          }

          console.log('sending settings:', settings);
          self.cb(self.parse(), settings);
        }
      },
      function() {
        delete self.inst;
      });
    },
    parse: function() {
      return _
        .chain(this.uris.trim().split(/\r?\n/g))
        .map(function(d) {
          return _(d)
            .replace(/["'][^"']*["']/g, function(c) {
              return c.replace(/%/g,'%25').replace(/ /g,'%20');
            })
            .trim()
            .split(/\s+/g)
            .map(function(c) {
              return c.replace(/%20/g,' ').replace(/%25/g,'%').replace(/["']/g,'');
            });
        })
        .filter(function(d) { return d.length })
        .value();
    }
  };

  scope.settings = {
    open: function(settings, title, actionText, cb) {
      var self = this;
      this.settings = settings;
      this.title = title;
      this.actionText = actionText;
      this.inst = $modal.open({
        templateUrl: "settings.html",
        scope: scope,
        windowClass: "modal-large"
      });
      this.inst.result.then(function() {
        delete self.inst;
        if (cb) {
          cb(self.settings);
        }
      },
      function() {
        delete self.inst;
      });
    }
  };

  scope.selectFiles = {
    open: function(files, cb) {
      var self = this;

	  this.files = _.cloneDeep(files);
      var groupFiles = function (files) {
          // sort files alphabetically
          files.sort(function (a, b) {
              if (a.relpath < b.relpath) {
                  return -1;
              } else {
                  return 1;
              }
          });
          function OrganizedFolder () {
              this.dirs = {};
              this.files = [];
              this.show = false;
              this.selected = true;
          }
          var folder = new OrganizedFolder(), tmp;
          for (var i = 0; i < files.length; i++) {
              tmp = folder;
              var str = files[i].relpath;
              var arr = str.split("/");
              for (var j = 0; j < arr.length - 1; j++) {
                  if (!tmp.dirs[arr[j]]) {
                      tmp.dirs[arr[j]] = new OrganizedFolder();
                  }
                  tmp = tmp.dirs[arr[j]];
              }
              tmp.files.push(files[i]);
          }
          return folder;
      };
      this.groupedFiles = groupFiles(this.files);
      this.inst = $modal.open({
        templateUrl: "selectFiles.html",
        scope: scope,
        windowClass: "modal-large"
      });

      this.inst.result.then(function() {
        delete self.inst;

        if (cb) {
          cb(self.files);
        }
      },
      function() {
        delete self.inst;
      });
    }
  };

  scope.connection = {
    open: function(defaults, cb) {
      var self = this;

      // XXX We need to actually clone this!
      this.conf = rpc.getConfiguration();
      this.inst = $modal.open({
        templateUrl: "connection.html",
        scope: scope,
        windowClass: "modal-large",
      });

      this.inst.result.then(function() {
        delete self.inst;
        if (cb) {
          cb(self.conf);
        }
      },
      function() {
        delete self.inst;
      });
    }
  };

  _.each(['getTorrents', 'getMetalinks'], function(name) {
    scope[name] = {
      open: function(cb) {
        var self = this;
        this.files = [];
        this.collapsed = true;
        this.settings = {};
        this.fsettings = _.cloneDeep(fsettings);

        // fill in default download properties
        _.forEach(dprops, function(p) {
          self.settings[p] = self.fsettings[p];
          delete self.fsettings[p];
        });

        this.inst = $modal.open({
          templateUrl: name + ".html",
          scope: scope,
          windowClass: "modal-large",
        });

        this.inst.result.then(function() {
          delete self.inst;
          if (cb) {
            parseFiles(self.files, function(txts) {
              var settings = {};

              // no need to send in default values, just the changed ones
              for (var i in self.settings) {
                if (fsettings[i].val != self.settings[i].val)
                    settings[i] = self.settings[i].val;
              }
              for (var i in self.fsettings) {
                if (fsettings[i].val != self.fsettings[i].val)
                    settings[i] = self.fsettings[i].val;
              }

              console.log('sending settings:', settings);
              cb(txts, settings);
            });
          }
        },
        function() {
          delete self.inst;
        });
      }
    };
  });

  _.each(["about", "server_info"], function(name) {
    scope[name] = {
      open: function() {
        var self = this;
        this.inst = $modal.open({
          templateUrl: name + ".html",
          scope: scope
        });
        this.inst.result.then(function() {
          delete self.inst;
        },
        function() {
          delete self.inst;
        });
      }
    };
  });

  rpc.once('getVersion', [], function(data) {
      scope.miscellaneous = data[0];
  });

  _.each([
    'getUris', 'getTorrents', 'getMetalinks', 'selectFiles',
    'settings', 'connection', 'server_info', 'about'
  ], function(name) {
    modals.register(name, function() {
      if (scope[name].inst) {
        // Already open.
        return;
      }
      var args = Array.prototype.slice.call(arguments, 0);
      scope[name].open.apply(scope[name], args);
    });
  });

}]);
