// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

/** Decoder class for decoding bytes using HDLC protocol */

import * as protocol from './protocol';
import * as util from './util';

const _MIN_FRAME_SIZE = 6; // 1 B address + 1 B control + 4 B CRC-32

/** Indicates if an error occurred */
export enum FrameStatus {
  OK = 'OK',
  FCS_MISMATCH = 'frame check sequence failure',
  FRAMING_ERROR = 'invalid flag or escape characters',
  BAD_ADDRESS = 'address field too long',
}

/**
 * A single HDLC frame
 */
export class Frame {
  rawEncoded: Uint8Array;
  rawDecoded: Uint8Array;
  status: FrameStatus;

  address = -1;
  control: Uint8Array = new Uint8Array();
  data: Uint8Array = new Uint8Array();

  constructor(
    rawEncoded: Uint8Array,
    rawDecoded: Uint8Array,
    status: FrameStatus = FrameStatus.OK
  ) {
    this.rawEncoded = rawEncoded;
    this.rawDecoded = rawDecoded;
    this.status = status;

    if (status === FrameStatus.OK) {
      const [address, addressLength] = protocol.decodeAddress(rawDecoded);
      if (addressLength === 0) {
        this.status = FrameStatus.BAD_ADDRESS;
        return;
      }
      this.address = address;
      this.control = rawDecoded.slice(addressLength, addressLength + 1);
      this.data = rawDecoded.slice(addressLength + 1, -4);
    }
  }

  /**
   * True if this represents a valid frame.
   *
   * If false, then parsing failed. The status is set to indicate what type of
   * error occurred, and the data field contains all bytes parsed from the frame
   * (including bytes parsed as address or control bytes).
   */
  ok(): boolean {
    return this.status === FrameStatus.OK;
  }
}

enum DecoderState {
  INTERFRAME,
  FRAME,
  FRAME_ESCAPE,
}

/** Decodes one or more HDLC frames from a stream of data. */
export class Decoder {
  private decodedData = new Uint8Array();
  private rawData = new Uint8Array();
  private state = DecoderState.INTERFRAME;

  constructor() {}

  /**
   *  Decodes and yields HDLC frames, including corrupt frames
   *
   *  The ok() method on Frame indicates whether it is valid or represents a
   *  frame parsing error.
   *
   *  @yield Frames, which may be valid (frame.ok)) okr corrupt (!frame.ok())
   */
  *process(data: Uint8Array): IterableIterator<Frame> {
    for (const byte of data) {
      const frame = this.processByte(byte);
      if (frame != null) {
        yield frame;
      }
    }
  }

  /**
   *  Decodes and yields valid HDLC frames, logging any errors.
   *
   *  @yield Valid HDLC frames
   */
  *processValidFrames(data: Uint8Array): IterableIterator<Frame> {
    const frames = this.process(data);
    for (const frame of frames) {
      if (frame.ok()) {
        yield frame;
      } else {
        console.warn(
          'Failed to decode frame: %s; discarded %d bytes',
          frame.status,
          frame.rawEncoded.length
        );
        console.debug('Discarded data: %s', frame.rawEncoded);
      }
    }
  }

  private checkFrame(data: Uint8Array): FrameStatus {
    if (data.length < _MIN_FRAME_SIZE) {
      return FrameStatus.FRAMING_ERROR;
    }
    const frameCrc = new DataView(data.slice(-4).buffer).getInt8(0);
    const crc = new DataView(
      protocol.frameCheckSequence(data.slice(0, -4)).buffer
    ).getInt8(0);
    if (crc !== frameCrc) {
      return FrameStatus.FCS_MISMATCH;
    }
    return FrameStatus.OK;
  }

  private finishFrame(status: FrameStatus): Frame {
    const frame = new Frame(
      new Uint8Array(this.rawData),
      new Uint8Array(this.decodedData),
      status
    );
    this.rawData = new Uint8Array();
    this.decodedData = new Uint8Array();
    return frame;
  }

  private processByte(byte: number): Frame | undefined {
    let frame;

    // Record every byte except the flag character.
    if (byte != protocol.FLAG) {
      this.rawData = util.concatenate(this.rawData, Uint8Array.of(byte));
    }

    switch (this.state) {
      case DecoderState.INTERFRAME:
        if (byte === protocol.FLAG) {
          if (this.rawData.length > 0) {
            frame = this.finishFrame(FrameStatus.FRAMING_ERROR);
          }
          this.state = DecoderState.FRAME;
        }
        break;

      case DecoderState.FRAME:
        if (byte == protocol.FLAG) {
          if (this.rawData.length > 0) {
            frame = this.finishFrame(this.checkFrame(this.decodedData));
          }
        } else if (byte == protocol.ESCAPE) {
          this.state = DecoderState.FRAME_ESCAPE;
        } else {
          this.decodedData = util.concatenate(
            this.decodedData,
            Uint8Array.of(byte)
          );
        }
        break;

      case DecoderState.FRAME_ESCAPE:
        if (byte === protocol.FLAG) {
          frame = this.finishFrame(FrameStatus.FRAMING_ERROR);
          this.state = DecoderState.FRAME;
        } else if (protocol.VALID_ESCAPED_BYTES.includes(byte)) {
          this.state = DecoderState.FRAME;
          this.decodedData = util.concatenate(
            this.decodedData,
            Uint8Array.of(protocol.escape(byte))
          );
        } else {
          this.state = DecoderState.INTERFRAME;
        }
        break;
    }
    return frame;
  }
}
