-- Copyright 2024 United States Government as represented by the Administrator
-- of the National Aeronautics and Space Administration. All Rights Reserved.
--
-- Disclaimers
--
-- 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.
--
-- | Diagrams.
module Data.Diagram
    ( Diagram(..)
    , diagramStates
    , diagramNumStates
    , diagramInitialState
    , diagramFinalState
    , diagramBadState
    )
  where

-- External imports
import Data.List (nub, sort)

-- | Internal representation for diagrams.
newtype Diagram = Diagram
    { Diagram -> [(Int, String, Int)]
diagramTransitions :: [(Int, String, Int)]
    }
  deriving (Int -> Diagram -> ShowS
[Diagram] -> ShowS
Diagram -> String
(Int -> Diagram -> ShowS)
-> (Diagram -> String) -> ([Diagram] -> ShowS) -> Show Diagram
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Diagram -> ShowS
showsPrec :: Int -> Diagram -> ShowS
$cshow :: Diagram -> String
show :: Diagram -> String
$cshowList :: [Diagram] -> ShowS
showList :: [Diagram] -> ShowS
Show, Diagram -> Diagram -> Bool
(Diagram -> Diagram -> Bool)
-> (Diagram -> Diagram -> Bool) -> Eq Diagram
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Diagram -> Diagram -> Bool
== :: Diagram -> Diagram -> Bool
$c/= :: Diagram -> Diagram -> Bool
/= :: Diagram -> Diagram -> Bool
Eq)

-- | States in a diagram.
diagramStates :: Diagram -> [Int]
diagramStates :: Diagram -> [Int]
diagramStates Diagram
diagram = [Int] -> [Int]
forall a. Eq a => [a] -> [a]
nub ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ [[Int]] -> [Int]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
  [ [Int
s, Int
d] | (Int
s, String
_, Int
d) <- Diagram -> [(Int, String, Int)]
diagramTransitions Diagram
diagram ]

-- | Number of states in a diagram.
diagramNumStates :: Diagram -> Int
diagramNumStates :: Diagram -> Int
diagramNumStates = [Int] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([Int] -> Int) -> (Diagram -> [Int]) -> Diagram -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Diagram -> [Int]
diagramStates

-- | Initial state of a diagram.
diagramInitialState :: Diagram -> Int
diagramInitialState :: Diagram -> Int
diagramInitialState = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([Int] -> Int) -> (Diagram -> [Int]) -> Diagram -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Diagram -> [Int]
diagramStates

-- | Final state of a diagram.
--
-- PRE: The diagram obtains one and only one final state.
diagramFinalState :: Diagram -> Int
diagramFinalState :: Diagram -> Int
diagramFinalState = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum ([Int] -> Int) -> (Diagram -> [Int]) -> Diagram -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Diagram -> [Int]
diagramStates

-- | Return a state value that does not represent any state in the diagram.
diagramBadState :: Diagram -> Int
diagramBadState :: Diagram -> Int
diagramBadState Diagram
diag = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum (Diagram -> [Int]
diagramStates Diagram
diag) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1