'use strict';

var PromiseA = require('bluebird');
var fs = PromiseA.promisifyAll(require('fs'));
var path = require('path');
//var oauth3dir = process.cwd();
var oauth3dir = path.join(require('os').homedir(), '.oauth3', 'v1');
var sessionsdir = path.join(oauth3dir, 'sessions');
var directivesdir = path.join(oauth3dir, 'directives');
var metadir = path.join(oauth3dir, 'meta');

// We can reasonably assume the existence of the home directory, but we can't assume
// that there will already be a `.oauth3` directory or anything inside of it.
if (!fs.existsSync(path.join(oauth3dir, '..'))) {
  fs.mkdirSync(path.join(oauth3dir, '..'));
}
if (!fs.existsSync(oauth3dir)) {
  fs.mkdirSync(oauth3dir);
}
if (!fs.existsSync(directivesdir)) {
  fs.mkdirSync(directivesdir);
}
if (!fs.existsSync(sessionsdir)) {
  fs.mkdirSync(sessionsdir);
}
if (!fs.existsSync(metadir)) {
  fs.mkdirSync(metadir);
}

module.exports = {
  directives: {
    all: function () {
      return fs.readdirAsync(directivesdir).then(function (nodes) {
        return nodes.map(function (node) {
          try {
            return require(path.join(directivesdir, node));
          } catch(e) {
            return null;
          }
        }).filter(Boolean);
      });
    }
  , get: function (providerUri) {
      // TODO make safe
      try {
        return require(path.join(directivesdir, providerUri + '.json'));
      } catch(e) {
        return null;
      }
    }
  , set: function (providerUri, directives) {
      return fs.writeFileAsync(
        path.join(directivesdir, providerUri + '.json')
      , JSON.stringify(directives, null, 2)
      ).then(function () {
        return directives;
      });
    }
  , clear: function () {
      return fs.readdirAsync(directivesdir).then(function (nodes) {
        return PromiseA.all(nodes.map(function (node) {
          return fs.unlinkAsync(path.join(directivesdir, node)).then(function () { }, function () { });
        }));
      });
    }
  }

, sessions: {
    all: function (providerUri) {
      return fs.readdirAsync(sessionsdir).then(function (nodes) {
        return nodes.map(function (node) {
          var result = require(path.join(sessionsdir, node));
          if (result.link) {
            return null;
          }
        }).filter(Boolean).filter(function (result) {
          if (!providerUri || providerUri === result.issuer) {
            return result;
          }
        });
      });
    }
  , get: function (providerUri, id) {
      var result;
      try {
        if (id) {
          return PromiseA.resolve(require(path.join(sessionsdir, providerUri + '.' + id + '.json')));
        }
        else {
          result = require(path.join(sessionsdir, providerUri + '.json'));
          // TODO make safer
          if (result.link && '/' !== result.link[0] && !/\.\./.test(result.link)) {
            result = require(path.join(sessionsdir, result.link));
          }
        }
      } catch(e) {
        return PromiseA.resolve(null);
      }
      return PromiseA.resolve(result);
    }
  , set: function (providerUri, session, id) {
      var p;

      if (id) {
        p = fs.writeFileAsync(path.join(sessionsdir, providerUri + '.' + id + '.json'), JSON.stringify(session, null, 2));
      }
      else {
        p = fs.writeFileAsync(path.join(sessionsdir, providerUri + '.json'), JSON.stringify(session, null, 2));
      }
      return p.then(function () {
        return session;
      });
    }
  , clear: function () {
      return fs.readdirAsync(sessionsdir).then(function (nodes) {
        return PromiseA.all(nodes.map(function (node) {
          return fs.unlinkAsync(path.join(sessionsdir, node));
        }));
      });
    }
  }
, meta: {
    get: function (key) {
      // TODO make safe
      try {
        return PromiseA.resolve(require(path.join(metadir, key + '.json')));
      } catch(e) {
        return PromiseA.resolve(null);
      }
    }
  , set: function (key, value) {
      return fs.writeFileAsync(path.join(metadir, key + '.json'), JSON.stringify(value, null, 2)).then(function () {
        return value;
      });
    }
  }
};