module Unison.Codebase.Editor.RemoteRepo where

import Unison.Codebase.Path (Path)
import Unison.Codebase.Path qualified as Path
import Unison.NameSegment qualified as NameSegment
import Unison.Prelude
import Unison.Project (ProjectAndBranch (..), ProjectBranchName, ProjectName)
import Unison.Share.Types
import Unison.Util.Recursion qualified as Rec

data ShareCodeserver
  = DefaultCodeserver
  | CustomCodeserver CodeserverURI
  deriving stock (ShareCodeserver -> ShareCodeserver -> Bool
(ShareCodeserver -> ShareCodeserver -> Bool)
-> (ShareCodeserver -> ShareCodeserver -> Bool)
-> Eq ShareCodeserver
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ShareCodeserver -> ShareCodeserver -> Bool
== :: ShareCodeserver -> ShareCodeserver -> Bool
$c/= :: ShareCodeserver -> ShareCodeserver -> Bool
/= :: ShareCodeserver -> ShareCodeserver -> Bool
Eq, Eq ShareCodeserver
Eq ShareCodeserver =>
(ShareCodeserver -> ShareCodeserver -> Ordering)
-> (ShareCodeserver -> ShareCodeserver -> Bool)
-> (ShareCodeserver -> ShareCodeserver -> Bool)
-> (ShareCodeserver -> ShareCodeserver -> Bool)
-> (ShareCodeserver -> ShareCodeserver -> Bool)
-> (ShareCodeserver -> ShareCodeserver -> ShareCodeserver)
-> (ShareCodeserver -> ShareCodeserver -> ShareCodeserver)
-> Ord ShareCodeserver
ShareCodeserver -> ShareCodeserver -> Bool
ShareCodeserver -> ShareCodeserver -> Ordering
ShareCodeserver -> ShareCodeserver -> ShareCodeserver
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ShareCodeserver -> ShareCodeserver -> Ordering
compare :: ShareCodeserver -> ShareCodeserver -> Ordering
$c< :: ShareCodeserver -> ShareCodeserver -> Bool
< :: ShareCodeserver -> ShareCodeserver -> Bool
$c<= :: ShareCodeserver -> ShareCodeserver -> Bool
<= :: ShareCodeserver -> ShareCodeserver -> Bool
$c> :: ShareCodeserver -> ShareCodeserver -> Bool
> :: ShareCodeserver -> ShareCodeserver -> Bool
$c>= :: ShareCodeserver -> ShareCodeserver -> Bool
>= :: ShareCodeserver -> ShareCodeserver -> Bool
$cmax :: ShareCodeserver -> ShareCodeserver -> ShareCodeserver
max :: ShareCodeserver -> ShareCodeserver -> ShareCodeserver
$cmin :: ShareCodeserver -> ShareCodeserver -> ShareCodeserver
min :: ShareCodeserver -> ShareCodeserver -> ShareCodeserver
Ord, Int -> ShareCodeserver -> ShowS
[ShareCodeserver] -> ShowS
ShareCodeserver -> String
(Int -> ShareCodeserver -> ShowS)
-> (ShareCodeserver -> String)
-> ([ShareCodeserver] -> ShowS)
-> Show ShareCodeserver
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ShareCodeserver -> ShowS
showsPrec :: Int -> ShareCodeserver -> ShowS
$cshow :: ShareCodeserver -> String
show :: ShareCodeserver -> String
$cshowList :: [ShareCodeserver] -> ShowS
showList :: [ShareCodeserver] -> ShowS
Show)

newtype ShareUserHandle = ShareUserHandle {ShareUserHandle -> Text
shareUserHandleToText :: Text}
  deriving stock (ShareUserHandle -> ShareUserHandle -> Bool
(ShareUserHandle -> ShareUserHandle -> Bool)
-> (ShareUserHandle -> ShareUserHandle -> Bool)
-> Eq ShareUserHandle
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ShareUserHandle -> ShareUserHandle -> Bool
== :: ShareUserHandle -> ShareUserHandle -> Bool
$c/= :: ShareUserHandle -> ShareUserHandle -> Bool
/= :: ShareUserHandle -> ShareUserHandle -> Bool
Eq, Eq ShareUserHandle
Eq ShareUserHandle =>
(ShareUserHandle -> ShareUserHandle -> Ordering)
-> (ShareUserHandle -> ShareUserHandle -> Bool)
-> (ShareUserHandle -> ShareUserHandle -> Bool)
-> (ShareUserHandle -> ShareUserHandle -> Bool)
-> (ShareUserHandle -> ShareUserHandle -> Bool)
-> (ShareUserHandle -> ShareUserHandle -> ShareUserHandle)
-> (ShareUserHandle -> ShareUserHandle -> ShareUserHandle)
-> Ord ShareUserHandle
ShareUserHandle -> ShareUserHandle -> Bool
ShareUserHandle -> ShareUserHandle -> Ordering
ShareUserHandle -> ShareUserHandle -> ShareUserHandle
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: ShareUserHandle -> ShareUserHandle -> Ordering
compare :: ShareUserHandle -> ShareUserHandle -> Ordering
$c< :: ShareUserHandle -> ShareUserHandle -> Bool
< :: ShareUserHandle -> ShareUserHandle -> Bool
$c<= :: ShareUserHandle -> ShareUserHandle -> Bool
<= :: ShareUserHandle -> ShareUserHandle -> Bool
$c> :: ShareUserHandle -> ShareUserHandle -> Bool
> :: ShareUserHandle -> ShareUserHandle -> Bool
$c>= :: ShareUserHandle -> ShareUserHandle -> Bool
>= :: ShareUserHandle -> ShareUserHandle -> Bool
$cmax :: ShareUserHandle -> ShareUserHandle -> ShareUserHandle
max :: ShareUserHandle -> ShareUserHandle -> ShareUserHandle
$cmin :: ShareUserHandle -> ShareUserHandle -> ShareUserHandle
min :: ShareUserHandle -> ShareUserHandle -> ShareUserHandle
Ord, Int -> ShareUserHandle -> ShowS
[ShareUserHandle] -> ShowS
ShareUserHandle -> String
(Int -> ShareUserHandle -> ShowS)
-> (ShareUserHandle -> String)
-> ([ShareUserHandle] -> ShowS)
-> Show ShareUserHandle
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ShareUserHandle -> ShowS
showsPrec :: Int -> ShareUserHandle -> ShowS
$cshow :: ShareUserHandle -> String
show :: ShareUserHandle -> String
$cshowList :: [ShareUserHandle] -> ShowS
showList :: [ShareUserHandle] -> ShowS
Show)

-- |
-- >>> :set -XOverloadedLists
-- >>> import Data.Maybe (fromJust)
-- >>> import Network.URI
-- >>> displayShareCodeserver DefaultCodeserver "share" ["base", "List"]
-- "share.base.List"
-- >>> displayShareCodeserver DefaultCodeserver "share" []
-- "share"
-- >>> displayShareCodeserver (CustomCodeserver . fromJust $ parseURI "https://share-next.unison-lang.org/api" >>= codeserverFromURI ) "unison" ["base", "List"]
-- "share(https://share-next.unison-lang.org:443/api).unison.base.List"
displayShareCodeserver :: ShareCodeserver -> ShareUserHandle -> Path -> Text
displayShareCodeserver :: ShareCodeserver -> ShareUserHandle -> Path -> Text
displayShareCodeserver ShareCodeserver
cs ShareUserHandle
shareUser Path
path =
  let shareServer :: Text
shareServer = case ShareCodeserver
cs of
        ShareCodeserver
DefaultCodeserver -> Text
""
        CustomCodeserver CodeserverURI
cu -> Text
"share(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> CodeserverURI -> Text
forall a. Show a => a -> Text
tShow CodeserverURI
cu Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")."
   in Text
shareServer Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ShareUserHandle -> Text
shareUserHandleToText ShareUserHandle
shareUser Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Path -> Text
maybePrintPath Path
path

-- | print remote namespace
printReadRemoteNamespace :: (a -> Text) -> ReadRemoteNamespace a -> Text
printReadRemoteNamespace :: forall a. (a -> Text) -> ReadRemoteNamespace a -> Text
printReadRemoteNamespace a -> Text
printProject = \case
  ReadShare'LooseCode ReadShareLooseCode {ShareCodeserver
server :: ShareCodeserver
$sel:server:ReadShareLooseCode :: ReadShareLooseCode -> ShareCodeserver
server, ShareUserHandle
repo :: ShareUserHandle
$sel:repo:ReadShareLooseCode :: ReadShareLooseCode -> ShareUserHandle
repo, Path
path :: Path
$sel:path:ReadShareLooseCode :: ReadShareLooseCode -> Path
path} -> ShareCodeserver -> ShareUserHandle -> Path -> Text
displayShareCodeserver ShareCodeserver
server ShareUserHandle
repo Path
path
  ReadShare'ProjectBranch a
project -> a -> Text
printProject a
project

-- | Render a 'WriteRemoteNamespace' as text.
printWriteRemoteNamespace :: (ProjectAndBranch ProjectName ProjectBranchName) -> Text
printWriteRemoteNamespace :: ProjectAndBranch ProjectName ProjectBranchName -> Text
printWriteRemoteNamespace ProjectAndBranch ProjectName ProjectBranchName
projectAndBranch = forall target source. From source target => source -> target
into @Text ProjectAndBranch ProjectName ProjectBranchName
projectAndBranch

maybePrintPath :: Path -> Text
maybePrintPath :: Path -> Text
maybePrintPath Path
path =
  if Path
path Path -> Path -> Bool
forall a. Eq a => a -> a -> Bool
== Path
forall a. Monoid a => a
mempty
    then Text
forall a. Monoid a => a
mempty
    else Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Path -> Text
forall path. Pathy path => path -> Text
Path.toText Path
path

data ReadRemoteNamespace a
  = ReadShare'LooseCode !ReadShareLooseCode
  | -- | A remote project+branch, specified by name (e.g. @unison/base/main).
    -- Currently assumed to be hosted on Share, though we could include a ShareCodeserver in here, too.
    ReadShare'ProjectBranch !a
  deriving stock (ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool
(ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool)
-> (ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool)
-> Eq (ReadRemoteNamespace a)
forall a.
Eq a =>
ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a.
Eq a =>
ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool
== :: ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool
$c/= :: forall a.
Eq a =>
ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool
/= :: ReadRemoteNamespace a -> ReadRemoteNamespace a -> Bool
Eq, (forall a b.
 (a -> b) -> ReadRemoteNamespace a -> ReadRemoteNamespace b)
-> (forall a b.
    a -> ReadRemoteNamespace b -> ReadRemoteNamespace a)
-> Functor ReadRemoteNamespace
forall a b. a -> ReadRemoteNamespace b -> ReadRemoteNamespace a
forall a b.
(a -> b) -> ReadRemoteNamespace a -> ReadRemoteNamespace b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b.
(a -> b) -> ReadRemoteNamespace a -> ReadRemoteNamespace b
fmap :: forall a b.
(a -> b) -> ReadRemoteNamespace a -> ReadRemoteNamespace b
$c<$ :: forall a b. a -> ReadRemoteNamespace b -> ReadRemoteNamespace a
<$ :: forall a b. a -> ReadRemoteNamespace b -> ReadRemoteNamespace a
Functor, Int -> ReadRemoteNamespace a -> ShowS
[ReadRemoteNamespace a] -> ShowS
ReadRemoteNamespace a -> String
(Int -> ReadRemoteNamespace a -> ShowS)
-> (ReadRemoteNamespace a -> String)
-> ([ReadRemoteNamespace a] -> ShowS)
-> Show (ReadRemoteNamespace a)
forall a. Show a => Int -> ReadRemoteNamespace a -> ShowS
forall a. Show a => [ReadRemoteNamespace a] -> ShowS
forall a. Show a => ReadRemoteNamespace a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> ReadRemoteNamespace a -> ShowS
showsPrec :: Int -> ReadRemoteNamespace a -> ShowS
$cshow :: forall a. Show a => ReadRemoteNamespace a -> String
show :: ReadRemoteNamespace a -> String
$cshowList :: forall a. Show a => [ReadRemoteNamespace a] -> ShowS
showList :: [ReadRemoteNamespace a] -> ShowS
Show, (forall x. ReadRemoteNamespace a -> Rep (ReadRemoteNamespace a) x)
-> (forall x.
    Rep (ReadRemoteNamespace a) x -> ReadRemoteNamespace a)
-> Generic (ReadRemoteNamespace a)
forall x. Rep (ReadRemoteNamespace a) x -> ReadRemoteNamespace a
forall x. ReadRemoteNamespace a -> Rep (ReadRemoteNamespace a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (ReadRemoteNamespace a) x -> ReadRemoteNamespace a
forall a x. ReadRemoteNamespace a -> Rep (ReadRemoteNamespace a) x
$cfrom :: forall a x. ReadRemoteNamespace a -> Rep (ReadRemoteNamespace a) x
from :: forall x. ReadRemoteNamespace a -> Rep (ReadRemoteNamespace a) x
$cto :: forall a x. Rep (ReadRemoteNamespace a) x -> ReadRemoteNamespace a
to :: forall x. Rep (ReadRemoteNamespace a) x -> ReadRemoteNamespace a
Generic)

data ReadShareLooseCode = ReadShareLooseCode
  { ReadShareLooseCode -> ShareCodeserver
server :: !ShareCodeserver,
    ReadShareLooseCode -> ShareUserHandle
repo :: !ShareUserHandle,
    -- sch :: Maybe ShortCausalHash, -- maybe later
    ReadShareLooseCode -> Path
path :: !Path
  }
  deriving stock (ReadShareLooseCode -> ReadShareLooseCode -> Bool
(ReadShareLooseCode -> ReadShareLooseCode -> Bool)
-> (ReadShareLooseCode -> ReadShareLooseCode -> Bool)
-> Eq ReadShareLooseCode
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ReadShareLooseCode -> ReadShareLooseCode -> Bool
== :: ReadShareLooseCode -> ReadShareLooseCode -> Bool
$c/= :: ReadShareLooseCode -> ReadShareLooseCode -> Bool
/= :: ReadShareLooseCode -> ReadShareLooseCode -> Bool
Eq, Int -> ReadShareLooseCode -> ShowS
[ReadShareLooseCode] -> ShowS
ReadShareLooseCode -> String
(Int -> ReadShareLooseCode -> ShowS)
-> (ReadShareLooseCode -> String)
-> ([ReadShareLooseCode] -> ShowS)
-> Show ReadShareLooseCode
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ReadShareLooseCode -> ShowS
showsPrec :: Int -> ReadShareLooseCode -> ShowS
$cshow :: ReadShareLooseCode -> String
show :: ReadShareLooseCode -> String
$cshowList :: [ReadShareLooseCode] -> ShowS
showList :: [ReadShareLooseCode] -> ShowS
Show)

isPublic :: ReadShareLooseCode -> Bool
isPublic :: ReadShareLooseCode -> Bool
isPublic ReadShareLooseCode {Path
$sel:path:ReadShareLooseCode :: ReadShareLooseCode -> Path
path :: Path
path} = case Path -> XNor NameSegment Path
forall t (f :: * -> *). Recursive t f => t -> f t
Rec.project Path
path of
  XNor NameSegment Path
Rec.Neither -> Bool
False
  Rec.Both NameSegment
segment Path
_ -> NameSegment
segment NameSegment -> NameSegment -> Bool
forall a. Eq a => a -> a -> Bool
== NameSegment
NameSegment.publicLooseCodeSegment