// 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.

///|
/// Arrowhead types for diago diagram edges
///
/// This enum represents all supported arrowhead types in diago diagrams.
/// Each arrowhead has its own marker rendering for SVG output.

///|
/// All supported arrowhead types
pub(all) enum ArrowheadType {
  /// No arrowhead
  None
  /// Default filled triangle arrow
  Triangle
  /// Filled arrow with a concave tail
  Arrow
  /// Unfilled diamond shape
  Diamond
  /// Filled diamond shape
  FilledDiamond
  /// Unfilled circle
  Circle
  /// Filled circle
  FilledCircle
  /// Open (unfilled) triangle arrow
  Open
  /// Simple line terminator
  Line
  /// Crow's foot: exactly one (vertical line)
  CfOne
  /// Crow's foot: zero or more (crow's foot)
  CfMany
  /// Crow's foot: exactly one, required (line with perpendicular)
  CfOneRequired
  /// Crow's foot: one or more, required (crow's foot with line)
  CfManyRequired
  /// Crow's foot: zero or one, optional (line with circle)
  CfOneOptional
  /// Crow's foot: zero or more, optional (crow's foot with circle)
  CfManyOptional
} derive(Eq, Debug)

///|
pub impl Show for ArrowheadType with fn output(self, logger) {
  logger.write_string(self.to_arrowhead_string())
}

///|
/// Parse an arrowhead type from a string
pub fn ArrowheadType::from_string(s : String) -> ArrowheadType {
  match s.to_lower() {
    "none" | "" => None
    "triangle" => Triangle
    "arrow" => Arrow
    "diamond" => Diamond
    "filled-diamond" => FilledDiamond
    "circle" => Circle
    "filled-circle" => FilledCircle
    "open" => Open
    "line" => Line
    "cf-one" | "cfone" => CfOne
    "cf-many" | "cfmany" => CfMany
    "cf-one-required" | "cfonerequired" => CfOneRequired
    "cf-many-required" | "cfmanyrequired" => CfManyRequired
    "cf-one-optional" | "cfoneoptional" => CfOneOptional
    "cf-many-optional" | "cfmanyoptional" => CfManyOptional
    _ => Triangle // Default to triangle for unknown types
  }
}

///|
/// Convert arrowhead type to canonical string representation
pub fn ArrowheadType::to_arrowhead_string(self : ArrowheadType) -> String {
  match self {
    None => "none"
    Triangle => "triangle"
    Arrow => "arrow"
    Diamond => "diamond"
    FilledDiamond => "filled-diamond"
    Circle => "circle"
    FilledCircle => "filled-circle"
    Open => "open"
    Line => "line"
    CfOne => "cf-one"
    CfMany => "cf-many"
    CfOneRequired => "cf-one-required"
    CfManyRequired => "cf-many-required"
    CfOneOptional => "cf-one-optional"
    CfManyOptional => "cf-many-optional"
  }
}

///|
/// Get the SVG marker ID for this arrowhead type
pub fn ArrowheadType::marker_id(self : ArrowheadType, reverse : Bool) -> String {
  let base = match self {
    None => return "" // No marker needed
    Triangle => "arrow-triangle"
    Arrow => "arrow"
    Diamond => "arrow-diamond"
    FilledDiamond => "arrow-diamond-filled"
    Circle => "arrow-circle"
    FilledCircle => "arrow-circle-filled"
    Open => "arrow-open"
    Line => "arrow-line"
    CfOne => "arrow-cf-one"
    CfMany => "arrow-cf-many"
    CfOneRequired => "arrow-cf-one-required"
    CfManyRequired => "arrow-cf-many-required"
    CfOneOptional => "arrow-cf-one-optional"
    CfManyOptional => "arrow-cf-many-optional"
  }
  if reverse {
    base + "-reverse"
  } else {
    base
  }
}

///|
/// Get the marker URL for SVG use
pub fn ArrowheadType::marker_url(
  self : ArrowheadType,
  reverse : Bool,
) -> String {
  let id = self.marker_id(reverse)
  if id.is_empty() {
    ""
  } else {
    "url(#" + id + ")"
  }
}

///|
/// Check if this is a crow's foot notation type
pub fn ArrowheadType::is_crows_foot(self : ArrowheadType) -> Bool {
  match self {
    CfOne
    | CfMany
    | CfOneRequired
    | CfManyRequired
    | CfOneOptional
    | CfManyOptional => true
    _ => false
  }
}

///|
/// Get ASCII representation of this arrowhead
pub fn ArrowheadType::to_ascii(self : ArrowheadType, reverse : Bool) -> String {
  match self {
    None => if reverse { "-" } else { "-" }
    Triangle => if reverse { "<" } else { ">" }
    Arrow => if reverse { "<" } else { ">" }
    Diamond | FilledDiamond => if reverse { "<>" } else { "<>" }
    Circle | FilledCircle => if reverse { "o" } else { "o" }
    Open => if reverse { "<" } else { ">" }
    Line => if reverse { "|" } else { "|" }
    CfOne => if reverse { "|" } else { "|" }
    CfMany => if reverse { "<" } else { ">" }
    CfOneRequired => if reverse { "||" } else { "||" }
    CfManyRequired => if reverse { "<|" } else { "|>" }
    CfOneOptional => if reverse { "o|" } else { "|o" }
    CfManyOptional => if reverse { "o<" } else { ">o" }
  }
}