// Copyright 2025 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(all) struct KeyData {
  idx : Int
  version : Int
} derive(Eq, Compare, Hash, Debug)

///|
pub impl Show for KeyData with output(self, logger) {
  if self.is_null() {
    logger.write_string("null")
  } else {
    logger..write_object(self.idx)..write_char('v').write_object(self.version)
  }
}

///|
pub fn KeyData::null() -> KeyData {
  { idx: -1, version: 1 }
}

///|
pub fn KeyData::default() -> KeyData {
  KeyData::null()
}

///|
pub fn KeyData::is_null(self : KeyData) -> Bool {
  self.idx < 0
}

///|
pub fn KeyData::index(self : KeyData) -> Int {
  self.idx
}

///|
pub fn KeyData::version(self : KeyData) -> Int {
  self.version
}

///|
pub fn KeyData::from_raw_parts(index : Int, version : Int) -> KeyData {
  { idx: index, version }
}

///|
pub fn KeyData::into_raw_parts(self : KeyData) -> (Int, Int) {
  (self.idx, self.version)
}

///|
pub(open) trait Key: Eq + Show {
  null() -> Self
  is_null(Self) -> Bool
  index(Self) -> Int
  version(Self) -> Int
  from_raw_parts(Int, Int) -> Self
  into_raw_parts(Self) -> (Int, Int)
}

///|
pub struct DefaultKey {
  data : KeyData
} derive(Eq, Compare, Hash, Debug)

///|
pub impl Show for DefaultKey with output(self, logger) {
  logger.write_object(self.data)
}

///|
pub impl Key for DefaultKey with null() {
  { data: KeyData::null() }
}

///|
pub impl Key for DefaultKey with is_null(self) {
  self.data.is_null()
}

///|
pub impl Key for DefaultKey with index(self) {
  self.data.index()
}

///|
pub impl Key for DefaultKey with version(self) {
  self.data.version()
}

///|
pub impl Key for DefaultKey with from_raw_parts(index, version) {
  { data: KeyData::from_raw_parts(index, version) }
}

///|
pub impl Key for DefaultKey with into_raw_parts(self) {
  self.data.into_raw_parts()
}

///|
pub impl Default for DefaultKey with default() {
  DefaultKey::null()
}