// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import chai from 'chai'; // not esm
import * as constant from '../src/constants';
import { ffxEventForTest, malformedLogForTest, symbolizedDataForTest } from './util';
import { FfxLogData, LogPayload } from '../src/log_data';
import { LogRow } from '../components/log_row';
import { messageForEvent } from '../src/format_log_text';

before(() => {
  chai.should();
});

/**
 * Creates a fake log data to be used in tests.
 *
 * @param payload payload to use for the fake log data.
 * @returns a log data to use for testing.
 */
function logDataForTest(payload: LogPayload): FfxLogData {
  return {
    data: {
      // eslint-disable-next-line @typescript-eslint/naming-convention
      TargetLog: {
        moniker: 'core/foo',
        metadata: {
          errors: [],
          // eslint-disable-next-line @typescript-eslint/naming-convention
          component_url: 'fuchsia-pkg://fuchsia.com/foo#metafoo.cm',
          timestamp: 12345678900,
          severity: 'Info',
          tags: ['bar', 'baz'],
          pid: 123,
          tid: 456,
          file: 'foo/main.rs',
          line: 25,
        },
        payload,
      },
    },
    timestamp: 12345,
    version: 1
  };
};

describe('LogRow', () => {
  describe('#constructor', () => {
    it('adds title to to non-message cells', async () => {
      const logRow = new LogRow(logDataForTest({
        root: {
          message: {
            value: 'hello vscode',
          },
          keys: null,
          printf: null,
        }
      }), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      const testFields = ['000012.35', '123', '456', 'core/foo', 'bar,baz', 'Info', 'hello vscode'];
      let field: keyof typeof testFields;
      for (field in testFields) {
        if (testFields[field] === 'hello vscode') {
          return;
        }
        const logField = logRow.children[0].children[field] as HTMLElement;
        logField.title.should.equal(testFields[field]);
      }
      logRow.remove();
    });

    it('formats target logs', async () => {
      const logRow = new LogRow(logDataForTest({
        root: {
          message: {
            value: 'hello vscode',
          },
          keys: null,
          printf: null,
        }
      }), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      const testFields = ['000012.35', '123', '456', 'core/foo', 'bar,baz', 'Info', 'hello vscode'];
      let field: keyof typeof testFields;
      for (field in testFields) {
        const logField = logRow.children[0].children[field] as HTMLElement;
        logField.innerText.should.equal(testFields[field]);
      }
      logRow.remove();
    });

    it('formats structured logs', async () => {
      const logRow = new LogRow(logDataForTest({
        root: {
          message: {
            value: 'hello vscode',
          },
          keys: {
            os: 'fuchsia',
            number: 1,
          },
          printf: null,
        }
      }), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      const testFields =
        ['000012.35', '123', '456', 'core/foo', 'bar,baz',
          'Info', 'hello vscodeos=fuchsia number=1'];
      let field: keyof typeof testFields;
      for (field in testFields) {
        const logField = logRow.children[0].children[field] as HTMLElement;
        logField.innerText.should.equal(testFields[field]);
      }
      logRow.remove();
    });

    it('formats printf logs', async () => {
      const logRow = new LogRow(logDataForTest({
        root: {
          message: null,
          keys: null,
          printf: {
            format: '%s is #%d',
            args: ['Fuchsia', 1]
          },
        }
      }), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      const testFields =
        ['000012.35', '123', '456', 'core/foo', 'bar,baz', 'Info', '%s is #%d args=[Fuchsia, 1]'];
      let field: keyof typeof testFields;
      for (field in testFields) {
        const logField = logRow.children[0].children[field] as HTMLElement;
        logField.innerText.should.equal(testFields[field]);
      }
      logRow.remove();
    });

    it('formats symbolized log', async () => {
      const logRow = new LogRow(symbolizedDataForTest({
        root: {
          message: {
            value: 'this is ignored',
          },
          keys: null,
          printf: null,
        }
      }), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      const testFields =
        ['000000.12', '123', '456', 'core/foo', 'my_tag', 'Info', 'symbolized'];
      let field: keyof typeof testFields;
      for (field in testFields) {
        const logField = logRow.children[0].children[field] as HTMLElement;
        logField.innerText.should.equal(testFields[field]);
      }
      logRow.remove();
    });

    it('formats logging started events', async () => {
      let logRow = new LogRow(ffxEventForTest('LoggingStarted'), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      let moniker = constant.FFX_MONIKER;
      let msg = messageForEvent('LoggingStarted', false);
      let monikerEl = logRow.children[0].children[3] as HTMLElement;
      let msgEl = logRow.children[0].children[6] as HTMLElement;

      monikerEl.innerText.should.equal(moniker);
      msgEl.innerText.should.equal(msg);
      logRow.remove();

      logRow = new LogRow(ffxEventForTest('LoggingStarted'), true);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      msg = messageForEvent('LoggingStarted', true);
      monikerEl = logRow.children[0].children[3] as HTMLElement;
      msgEl = logRow.children[0].children[6] as HTMLElement;

      monikerEl.innerText.should.equal(moniker);
      msgEl.innerText.should.equal(msg);
      logRow.remove();
    });

    it('formats target disconnected events', async () => {
      const logRow = new LogRow(ffxEventForTest('TargetDisconnected'), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      let moniker = constant.FFX_MONIKER;
      let msg = messageForEvent('TargetDisconnected', true);
      let monikerEl = logRow.children[0].children[3] as HTMLElement;
      let msgEl = logRow.children[0].children[6] as HTMLElement;

      monikerEl.innerText.should.equal(moniker);
      msgEl.innerText.should.equal(msg);
      logRow.remove();
    });

    it('formats malformed log', async () => {
      const logRow = new LogRow(malformedLogForTest('hello world'), false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      let msg = 'Malformed target log: hello world';
      let msgEl = logRow.children[0].children[6] as HTMLElement;
      msgEl.innerText.should.equal(msg);
      logRow.remove();
    });

    it('formats viewer synthesized messages', async () => {
      const msg = 'Logs are cool';
      const data = {
        data: {
          // eslint-disable-next-line @typescript-eslint/naming-convention
          ViewerEvent: msg,
        },
        timestamp: 0,
        version: 0
      };
      const logRow = new LogRow(data, false);
      document.body.appendChild(logRow);
      await logRow.updateComplete;
      const monikerEl = logRow.children[0].children[3] as HTMLElement;
      const msgEl = logRow.children[0].children[6] as HTMLElement;
      monikerEl.innerText.should.equal(constant.VSCODE_SYNTHETIC_MONIKER);
      msgEl.innerText.should.equal(msg);
      logRow.remove();
    });
  });
});
