/**
 * @file The starting point of Bastion
 * @author Sankarsan Kampa (a.k.a k3rn31p4nic)
 * @license GPL-3.0
 */

const Tesseract = xrequire('tesseract');
const BASTION = new Tesseract.Client({
  configurations: xrequire('./settings/config.json'),
  credentials: xrequire('./settings/credentials.json'),
  disabledEvents: [
    'USER_NOTE_UPDATE',
    'TYPING_START',
    'RELATIONSHIP_ADD',
    'RELATIONSHIP_REMOVE'
  ]
});

if (BASTION.shard) process.title = `Bastion-Shard-${BASTION.shard.id}`;
else process.title = 'BastionBot';

BASTION.package = xrequire('./package.json');
BASTION.Constants = Tesseract.Constants;
BASTION.colors = Tesseract.Constants.Colors;
BASTION.permissions = Tesseract.Permissions.FLAGS;

// xrequire('./prototypes/Array.prototype');
xrequire('./prototypes/String.prototype');
xrequire('./prototypes/Number.prototype');

const WebhookHandler = xrequire('./handlers/webhookHandler.js');
BASTION.webhook = new WebhookHandler(BASTION.credentials.webhooks);
BASTION.log = xrequire('./handlers/logHandler');
BASTION.methods = xrequire('./handlers/methodHandler');

const StringHandler = xrequire('./handlers/stringHandler');
BASTION.i18n = new StringHandler();

const Sequelize = xrequire('sequelize');
BASTION.database = new Sequelize(BASTION.credentials.database.URI, {
  operatorsAliases: false,
  logging: false
});
BASTION.database.authenticate().then(() => {
  // Populate Database/Implement model definitions
  xrequire('./utils/models')(Sequelize, BASTION.database);

  // Load Bastion Events
  xrequire('./handlers/eventHandler')(BASTION);

  // Load Bastion Modules
  const Modules = xrequire('./handlers/moduleHandler');
  BASTION.commands = Modules.commands;
  BASTION.aliases = Modules.aliases;

  // Start Bastion
  BASTION.login(BASTION.credentials.token).then(() => {
    /**
     * Using <Model>.findOrCreate() won't require the use of
     * <ModelInstance>.save() but <Model>.findOrBuild() is used instead because
     * <Model>.findOrCreate() creates a race condition where a matching row is
     * created by another connection after the `find` but before the `insert`
     * call. However, it is not always possible to handle this case in SQLite,
     * specifically if one transaction inserts and another tries to select
     * before the first one has committed. TimeoutError is thrown instead.
     */
    BASTION.database.models.settings.findOrBuild({
      where: {
        botID: BASTION.user.id
      }
    }).spread((settingsModel, initialized) => {
      if (initialized) {
        return settingsModel.save();
      }
    }).catch(BASTION.log.error);
  }).catch(e => {
    BASTION.log.error(e.toString());
    process.exit(1);
  });
}).catch(err => {
  BASTION.log.error(err);
});

process.on('unhandledRejection', rejection => {
  /* eslint-disable no-console */
  console.warn('\n[unhandledRejection]');
  console.warn(rejection);
  console.warn('[/unhandledRejection]\n');
  /* eslint-enable no-console */
});

@@ -194,114 +194,39 @@
 %7B%0A  
-configurations: xrequire('./settings/config.json'),%0A  credentials: xrequire('./settings/credentials.json')
+settingsDirectory: './settings'
 ,%0A  

set settingsDirectory Tesseract options