-- SPDX-FileCopyrightText: 2020 Tocqueville Group
--
-- SPDX-License-Identifier: LicenseRef-MIT-TQ

-- | List of functions that generate the files for 'FileGen'.
module FileGen.Files
  ( main
  , basic
  , mainTest
  , basicTest
  , changelog
  , readme
  , gitignore
  , packageYaml
  , stackYaml
  ) where

import Data.String.Interpolate (i)

import Helper

main :: Text
main = [i|module Main
  ( main
  ) where

import qualified Data.Map as Map
import qualified Options.Applicative as Opt
import Options.Applicative.Help.Pretty (Doc, linebreak)
import Main.Utf8 (withUtf8)
import Lorentz (DGitRevision(..))
import Lorentz.ContractRegistry
import System.Environment (withProgName)

import qualified Basic

programInfo :: DGitRevision -> Opt.ParserInfo CmdLnArgs
programInfo gitRev = Opt.info (Opt.helper <*> argParser contracts gitRev) $
  mconcat
  [ Opt.fullDesc
  , Opt.progDesc "#{indigoDesc}"
  , Opt.header "#{indigoTitle}"
  , Opt.footerDoc $ Just usageDoc
  ]

usageDoc :: Doc
usageDoc = mconcat
   [ "You can use help for specific COMMAND", linebreak
   , "EXAMPLE:", linebreak
   , "  #{indigoRunCommand} print --help", linebreak
   ]

contracts :: ContractRegistry
contracts = ContractRegistry $ Map.fromList
  [ "Basic" ?:: ContractInfo
    { ciContract = Basic.basicContractLorentz
    , ciIsDocumented = True
    , ciStorageParser = Just (pure Basic.emptyStorage)
    , ciStorageNotes = Nothing
    }
  ]

main :: IO ()
main = withUtf8 $ withProgName "#{indigoRunCommand}" $ do
  cmdLnArgs <- Opt.execParser (programInfo DGitRevisionUnknown)
  runContractRegistry contracts cmdLnArgs `catchAny` (die . displayException)
|]

basic :: Text
basic = [i|module Basic
  ( basicContractLorentz
  , emptyStorage
  ) where

import Indigo
import Lorentz.Run (Contract)

basicContractLorentz :: Contract Integer Integer
basicContractLorentz = defaultContract $ compileIndigoContract basicContract

basicContract :: IndigoContract Integer Integer
basicContract param = defContract do
  storage += param

emptyStorage :: Integer
emptyStorage = 0 int

storage :: HasStorage Integer => Var Integer
storage = storageVar
|]

basicTest :: Text
basicTest = [i|module Test.Basic
  ( unit_updates_storage_properly
  ) where

import Basic (basicContractLorentz)

import Lorentz
import Lorentz.Test
import Michelson.Test.Integrational
import Michelson.Typed.Convert
import Test.Tasty.HUnit (Assertion)

unit_updates_storage_properly :: Assertion
unit_updates_storage_properly = integrationalTestExpectation $ do
  contractAddr <- originate (convertContract $ compileLorentzContract basicContractLorentz) "basic"
          (untypeValue $ toVal (10 :: Integer)) (zeroMutez)

  let
    txData = TxData
      { tdSenderAddress = genesisAddress
      , tdParameter = TxTypedParam $ toVal (90 :: Integer)
      , tdEntrypoint = DefEpName
      , tdAmount = zeroMutez
      }

  transfer txData contractAddr

  expectStorageConst contractAddr
    $ untypeValue $ toVal (100 :: Integer)
|]

mainTest :: Text
mainTest = "{-# OPTIONS_GHC -F -pgmF tasty-discover #-}\n"

changelog :: Text -> Text
changelog projectName = [i|# Changelog for #{projectName}

## Unreleased changes
|]

readme :: Text -> Text
readme projectName = [i|# #{projectName}
|]

gitignore :: Text
gitignore = unlines
  [ ".stack-work/"
  , "*~"
  ]

packageYaml :: Text -> Text
packageYaml projectName = [i|name:                #{projectName}
version:             0.1.0.0
github:              "githubuser/#{projectName}"
author:              "Author name here"
maintainer:          "example@example.com"
copyright:           "2020 Author name here"

extra-source-files:
- README.md
- ChangeLog.md

description:         Please see the README on GitHub at <https://github.com/githubuser/#{projectName}#readme>

verbatim:
  cabal-version: 2.2

default-extensions:
  - AllowAmbiguousTypes
  - BangPatterns
  - BlockArguments
  - ConstraintKinds
  - DataKinds
  - DefaultSignatures
  - DeriveAnyClass
  - DeriveDataTypeable
  - DeriveFoldable
  - DeriveFunctor
  - DeriveGeneric
  - DeriveTraversable
  - DerivingStrategies
  - DerivingVia
  - EmptyCase
  - FlexibleContexts
  - FlexibleInstances
  - GADTs
  - GeneralizedNewtypeDeriving
  - LambdaCase
  - MultiParamTypeClasses
  - MultiWayIf
  - NamedFieldPuns
  - NegativeLiterals
  - NumDecimals
  - OverloadedLabels
  - OverloadedStrings
  - PatternSynonyms
  - PolyKinds
  - QuasiQuotes
  - RankNTypes
  - RecordWildCards
  - RecursiveDo
  - ScopedTypeVariables
  - StandaloneDeriving
  - StrictData
  - TemplateHaskell
  - TupleSections
  - TypeApplications
  - TypeFamilies
  - TypeOperators
  - UndecidableInstances
  - UndecidableSuperClasses
  - ViewPatterns

dependencies:
  - name: base
    version: ">= 4.7 && < 5"
    mixin: [hiding (Prelude)]

ghc-options:
  - -Weverything
  - -Wno-missing-exported-signatures
  - -Wno-missing-import-lists
  - -Wno-missed-specialisations
  - -Wno-all-missed-specialisations
  - -Wno-unsafe
  - -Wno-safe
  - -Wno-missing-local-signatures
  - -Wno-monomorphism-restriction
  - -Wno-implicit-prelude

library:
  source-dirs: src
  default-extensions: [ RebindableSyntax ]
  ghc-options: [ -Wno-unused-do-bind ]

  generated-other-modules:
    - Paths_#{useUnderscore projectName}

  dependencies:
    - containers
    - fmt
    - indigo
    - lorentz
    - morley
    - morley-prelude
    - text

executables:
  #{projectName}:
    main: Main.hs
    source-dirs: app

    dependencies:
      - #{projectName}
      - containers
      - morley
      - lorentz
      - indigo
      - morley-prelude
      - optparse-applicative
      - with-utf8

tests:
  #{projectName}-test:
    main:        Main.hs
    source-dirs: test
    build-tools: tasty-discover:tasty-discover
    ghc-options:
      - -threaded
      - -eventlog
      - -rtsopts
      - '"-with-rtsopts=-N -A64m -AL256m"'
    dependencies:
      - #{projectName}
      - cleveland
      - containers
      - fmt
      - hspec
      - hspec-expectations
      - HUnit
      - lorentz
      - morley
      - morley-prelude
      - tasty
      - tasty-hspec
      - tasty-hunit-compat
|]

stackYaml :: Text
stackYaml = [i|resolver: lts-16.5

packages:
  - .

extra-deps:
  - tasty-hunit-compat-0.2
  - morley-prelude-0.3.0
  - morley-1.6.0
  - lorentz-0.6.0
  - indigo-0.2.0
  - git:
      https://gitlab.com/morley-framework/morley.git
    commit:
      3bc23ad17a0719ee96d83a94b0194ca5bfe3b8c7 # morley-1.6.0
    subdirs:
      - code/cleveland
      - code/morley-client

  - base58-bytestring-0.1.0
  - hex-text-0.1.0.0
  - show-type-0.1.1
  - git: https://github.com/int-index/caps.git
    commit: c5d61837eb358989b581ed82b1e79158c4823b1b
  - named-0.3.0.1@sha256:69b9722301201f8ed8abc89c4595e22c746e944bf4cdfafa8b21b14d336b26d1,2233
  - vinyl-0.12.1@sha256:43456d4b3009646eee63953cbe539f1f4d0caf8bc3c25e841117e712836508f3,3790
  - cryptonite-0.27

nix:
  packages: [zlib]
|]
