{-# language DeriveAnyClass #-}
{-# language DeriveGeneric #-}
{-# language DerivingStrategies #-}
{-# language GeneralizedNewtypeDeriving #-}
{-# language OverloadedStrings #-}
{-# language ViewPatterns #-}
module Language.Elm.Name where

import Data.Bifunctor
import qualified Data.Char as Char
import Data.Hashable
import Data.String
import Data.Text (Text)
import qualified Data.Text as Text
import GHC.Generics (Generic)

type Module = [Text]

newtype Local = Local Text
  deriving stock (Eq, Ord, Show, Generic)
  deriving newtype (IsString)
  deriving anyclass (Hashable)

data Qualified = Qualified Module Text
  deriving (Eq, Ord, Show, Generic)
  deriving anyclass (Hashable)

newtype Field = Field Text
  deriving stock (Eq, Ord, Show, Generic)
  deriving newtype (IsString)
  deriving anyclass (Hashable)

newtype Constructor = Constructor Text
  deriving stock (Eq, Ord, Show, Generic)
  deriving newtype (IsString)
  deriving anyclass (Hashable)

isConstructor :: Qualified -> Bool
isConstructor name =
  case name of
    "List.::" ->
      True

    "Basics.," ->
      True

    "Basics.()" ->
      True

    Qualified _ (Text.uncons -> Just (firstChar, _)) ->
      Char.isUpper firstChar

    _ ->
      False

instance IsString Qualified where
  fromString s =
    case unsnoc $ Text.splitOn "." $ fromString s of
      Nothing ->
        error "Empty name"

      Just ([], x) ->
        error $ "Unqualified name " <> show x

      Just (xs, x) ->
        Qualified xs x
    where
      unsnoc :: [a] -> Maybe ([a], a)
      unsnoc [] = Nothing
      unsnoc (a:as) = Just $ go a as

      go :: a -> [a] -> ([a], a)
      go a [] = ([], a)
      go a (a':as) = first (a:) $ go a' as