// Copyright 2026 International Digital Economy Academy
//
// 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.

///|
pub struct Anchor {
  x : Int
  y : Int
} derive(Eq, Show, ToJson)

///|
pub struct AnkrTable {
  version : Int
  lookup : LookupTable
  anchor_offset : Int
  data : Bytes
} derive(Show, ToJson)

///|
pub fn AnkrTable::parse(
  data : BytesView,
  num_glyphs : Int,
) -> Result[AnkrTable, AatError] {
  let version = read_u16_int(data, 0)
  let flags = read_u16_int(data, 2)
  let lookup_offset = read_u32_non_negative(data, 4)
  let anchor_offset = read_u32_non_negative(data, 8)
  match (version, flags, lookup_offset, anchor_offset) {
    (Err(err), _, _, _) => Err(err)
    (_, Err(err), _, _) => Err(err)
    (_, _, Err(err), _) => Err(err)
    (_, _, _, Err(err)) => Err(err)
    (Ok(version), Ok(_), Ok(lookup_offset), Ok(anchor_offset)) => {
      if lookup_offset < 0 || anchor_offset < 0 {
        return Err(InvalidFormat)
      }
      if lookup_offset >= data.length() || anchor_offset >= data.length() {
        return Err(UnexpectedEof)
      }
      let lookup = match parse_lookup(data, lookup_offset, num_glyphs) {
        Err(err) => return Err(err)
        Ok(value) => value
      }
      Ok(AnkrTable::{
        version,
        lookup,
        anchor_offset,
        data: data.to_bytes(),
      })
    }
  }
}

///|
pub fn AnkrTable::has_data(self : AnkrTable) -> Bool {
  self.version == 0
}

///|
pub fn AnkrTable::get_anchor(
  self : AnkrTable,
  glyph : UInt,
  index : Int,
) -> Anchor? {
  if index < 0 {
    return None
  }
  let offset = match self.lookup.value_for(glyph) {
    None => return None
    Some(value) => value.reinterpret_as_int()
  }
  if offset < 0 {
    return None
  }
  let base = self.anchor_offset + offset
  if base < 0 || base + 4 > self.data.length() {
    return None
  }
  let count = match read_u32_non_negative(self.data[:], base) {
    Err(_) => return None
    Ok(value) => value
  }
  if index >= count {
    return None
  }
  let anchor_base = base + 4 + index * 4
  if anchor_base < 0 || anchor_base + 4 > self.data.length() {
    return None
  }
  let x = match read_i16(self.data[:], anchor_base) {
    Err(_) => return None
    Ok(value) => value
  }
  let y = match read_i16(self.data[:], anchor_base + 2) {
    Err(_) => return None
    Ok(value) => value
  }
  Some(Anchor::{ x, y })
}