/*
 * Copyright 2024 Google Inc. All rights reserved.
 *
 * 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
 *
 *     http://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.
 */

import Foundation

/// `TableVerifier` verifies a table object is within a provided memory.
/// It checks if all the objects for a specific generated table, are within
/// the bounds of the buffer, aligned.
public struct TableVerifier {

  /// position of current table in `ByteBuffer`
  fileprivate var _position: Int

  /// Current VTable position
  fileprivate var _vtable: Int

  /// Length of current VTable
  fileprivate var _vtableLength: Int

  /// `Verifier` object created in the base verifable call.
  fileprivate var _verifier: Verifier

  /// Creates a `TableVerifier` verifier that allows the Flatbuffer object
  /// to verify the buffer before accessing any of the data.
  ///
  /// - Parameters:
  ///   - position: Current table Position
  ///   - vtable: Current `VTable` position
  ///   - vtableLength: Current `VTable` length
  ///   - verifier: `Verifier` Object  that caches the data of the verifiable object
  internal init(
    position: Int,
    vtable: Int,
    vtableLength: Int,
    verifier: inout Verifier)
  {
    _position = position
    _vtable = vtable
    _vtableLength = vtableLength
    _verifier = verifier
  }

  /// Dereference the current object position from the `VTable`
  /// - Parameter field: Current VTable refrence to  position.
  /// - Throws: A `FlatbuffersErrors` incase the voffset is not aligned/outOfBounds/apparentSizeTooLarge
  /// - Returns: An optional position for current field
  internal mutating func dereference(_ field: VOffset) throws -> Int? {
    if field >= _vtableLength {
      return nil
    }

    /// Reading the offset for the field needs to be read.
    let offset: VOffset = try _verifier.getValue(
      at: Int(clamping: _vtable &+ Int(field)))

    if offset > 0 {
      return Int(clamping: _position &+ Int(offset))
    }
    return nil
  }

  /// Visits all the fields within the table to validate the integrity
  /// of the data
  /// - Parameters:
  ///   - field: voffset of the current field to be read
  ///   - fieldName: fieldname to report data Errors.
  ///   - required: If the field has to be available in the buffer
  ///   - type: Type of field to be read
  /// - Throws: A `FlatbuffersErrors` where the field is corrupt
  public mutating func visit<T>(
    field: VOffset,
    fieldName: String,
    required: Bool,
    type: T.Type) throws where T: Verifiable
  {
    let derefValue = try dereference(field)

    if let value = derefValue {
      try T.verify(&_verifier, at: value, of: T.self)
      return
    }
    if required {
      throw FlatbuffersErrors.requiredFieldDoesntExist(
        position: field,
        name: fieldName)
    }
  }

  /// Visits all the fields for a union object within the table to
  /// validate the integrity of the data
  /// - Parameters:
  ///   - key: Current Key Voffset
  ///   - field: Current field Voffset
  ///   - unionKeyName: Union key name
  ///   - fieldName: Field key name
  ///   - required: indicates if an object is required to be present
  ///   - completion: Completion is a handler that WILL be called in the generated
  /// - Throws: A `FlatbuffersErrors` where the field is corrupt
  public mutating func visit<T>(
    unionKey key: VOffset,
    unionField field: VOffset,
    unionKeyName: String,
    fieldName: String,
    required: Bool,
    completion: @escaping (inout Verifier, T, Int) throws -> Void) throws
    where T: UnionEnum
  {
    let keyPos = try dereference(key)
    let valPos = try dereference(field)

    if keyPos == nil && valPos == nil {
      if required {
        throw FlatbuffersErrors.requiredFieldDoesntExist(
          position: key,
          name: unionKeyName)
      }
      return
    }

    if let _key = keyPos,
       let _val = valPos
    {
      /// verifiying that the key is within the buffer
      try T.T.verify(&_verifier, at: _key, of: T.T.self)
      guard
        let _enum = try T.init(
          value: _verifier._buffer.read(
            def: T.T.self,
            position: _key))
      else {
        throw FlatbuffersErrors.unknownUnionCase
      }
      /// we are assuming that Unions will always be of type Uint8
      try completion(
        &_verifier,
        _enum,
        _val)
      return
    }
    throw FlatbuffersErrors.valueNotFound(
      key: keyPos,
      keyName: unionKeyName,
      field: valPos,
      fieldName: fieldName)
  }

  /// Visits and validates all the objects within a union vector
  /// - Parameters:
  ///   - key: Current Key Voffset
  ///   - field: Current field Voffset
  ///   - unionKeyName: Union key name
  ///   - fieldName: Field key name
  ///   - required: indicates if an object is required to be present
  ///   - completion: Completion is a handler that WILL be called in the generated
  /// - Throws: A `FlatbuffersErrors` where the field is corrupt
  public mutating func visitUnionVector<T>(
    unionKey key: VOffset,
    unionField field: VOffset,
    unionKeyName: String,
    fieldName: String,
    required: Bool,
    completion: @escaping (inout Verifier, T, Int) throws -> Void) throws
    where T: UnionEnum
  {
    let keyVectorPosition = try dereference(key)
    let offsetVectorPosition = try dereference(field)

    if let keyPos = keyVectorPosition,
       let valPos = offsetVectorPosition
    {
      try UnionVector<T>.verify(
        &_verifier,
        keyPosition: keyPos,
        fieldPosition: valPos,
        unionKeyName: unionKeyName,
        fieldName: fieldName,
        completion: completion)
      return
    }
    if required {
      throw FlatbuffersErrors.requiredFieldDoesntExist(
        position: field,
        name: fieldName)
    }
  }

  /// Finishs the current Table verifier, and subtracts the current
  /// table from the incremented depth.
  public mutating func finish() {
    _verifier.finish()
  }
}
