const { test } = require('tap');
const fs = require('fs');
const os = require('os');

const EOL = os.EOL || '\n';

const osDelay = process.platform === 'win32' ? 400 : 200;

function remove(filename) {
  try {
    fs.unlinkSync(filename);
  } catch (e) {
    // doesn't really matter if it failed
  }
}

test('log4js logLevelFilter', (batch) => {
  batch.test('appender', (t) => {
    const log4js = require('../../lib/log4js');
    const recording = require('../../lib/appenders/recording');

    log4js.configure({
      appenders: {
        recorder: { type: 'recording' },
        filtered: {
          type: 'logLevelFilter',
          appender: 'recorder',
          level: 'ERROR',
        },
      },
      categories: {
        default: { appenders: ['filtered'], level: 'debug' },
      },
    });

    const logger = log4js.getLogger('logLevelTest');
    logger.debug('this should not trigger an event');
    logger.warn('neither should this');
    logger.error('this should, though');
    logger.fatal('so should this');

    const logEvents = recording.replay();

    t.test(
      'should only pass log events greater than or equal to its own level',
      (assert) => {
        assert.equal(logEvents.length, 2);
        assert.equal(logEvents[0].data[0], 'this should, though');
        assert.equal(logEvents[1].data[0], 'so should this');
        assert.end();
      }
    );
    t.end();
  });

  batch.test('configure', (t) => {
    const log4js = require('../../lib/log4js');

    remove(`${__dirname}/logLevelFilter.log`);
    remove(`${__dirname}/logLevelFilter-warnings.log`);
    remove(`${__dirname}/logLevelFilter-debugs.log`);

    t.teardown(() => {
      remove(`${__dirname}/logLevelFilter.log`);
      remove(`${__dirname}/logLevelFilter-warnings.log`);
      remove(`${__dirname}/logLevelFilter-debugs.log`);
    });

    log4js.configure({
      appenders: {
        'warning-file': {
          type: 'file',
          filename: 'test/tap/logLevelFilter-warnings.log',
          layout: { type: 'messagePassThrough' },
        },
        warnings: {
          type: 'logLevelFilter',
          level: 'WARN',
          appender: 'warning-file',
        },
        'debug-file': {
          type: 'file',
          filename: 'test/tap/logLevelFilter-debugs.log',
          layout: { type: 'messagePassThrough' },
        },
        debugs: {
          type: 'logLevelFilter',
          level: 'TRACE',
          maxLevel: 'DEBUG',
          appender: 'debug-file',
        },
        tests: {
          type: 'file',
          filename: 'test/tap/logLevelFilter.log',
          layout: {
            type: 'messagePassThrough',
          },
        },
      },
      categories: {
        default: { appenders: ['tests', 'warnings', 'debugs'], level: 'trace' },
      },
    });
    const logger = log4js.getLogger('tests');
    logger.debug('debug');
    logger.info('info');
    logger.error('error');
    logger.warn('warn');
    logger.debug('debug');
    logger.trace('trace');
    // wait for the file system to catch up
    setTimeout(() => {
      t.test('logLevelFilter.log should contain all log messages', (assert) => {
        fs.readFile(
          `${__dirname}/logLevelFilter.log`,
          'utf8',
          (err, contents) => {
            const messages = contents.trim().split(EOL);
            assert.same(messages, [
              'debug',
              'info',
              'error',
              'warn',
              'debug',
              'trace',
            ]);
            assert.end();
          }
        );
      });
      t.test(
        'logLevelFilter-warnings.log should contain only error and warning logs',
        (assert) => {
          fs.readFile(
            `${__dirname}/logLevelFilter-warnings.log`,
            'utf8',
            (err, contents) => {
              const messages = contents.trim().split(EOL);
              assert.same(messages, ['error', 'warn']);
              assert.end();
            }
          );
        }
      );
      t.test(
        'logLevelFilter-debugs.log should contain only trace and debug logs',
        (assert) => {
          fs.readFile(
            `${__dirname}/logLevelFilter-debugs.log`,
            'utf8',
            (err, contents) => {
              const messages = contents.trim().split(EOL);
              assert.same(messages, ['debug', 'debug', 'trace']);
              assert.end();
            }
          );
        }
      );
      t.end();
    }, osDelay);
  });

  batch.end();
});
