pykick.psm1

$PYKICK_CONF_PS1 = @'
#:# PROJECT ########################################################################################
$Global:PythonProjectName = "chopper"
$Global:PythonProjectVersion = "1.0.0"
$Global:PythonProjectDescription = "Chopper greets you with a random quote from the One Piece manga =}"
$Global:PythonProjectAuthor = "Michel TRUONG"
$Global:PythonProjectAuthorEmail = "michel.truong@gmail.com"
$Global:PythonProjectPath = "./"
$Global:PythonProjectASCIILogo = @"
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠟⠛⠛⠛⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠛⠛⠿
⣿⣿⣿⡿⢛⣩⣭⣉⠻⠿⣿⣿⣿⣿⣿⣿⣿⠿⠛⣉⠉⠁⠀⠀⢀⣤⣤⠀⠀⠀⠀⠀⠀⠉⠙⠻⢿⣿⣿⣿⡟⣡⣶⣿⣿⣆⠙⡛⢿
⣿⣿⡟⣰⣿⣿⣿⡟⣸⣦⢸⣿⣿⣿⠿⠋⠀⠠⠾⣛⣀⣠⣤⣀⣬⣉⣉⡀⠀⠀⣴⣦⡀⠀⠀⠀⠀⠈⠻⠏⣼⣿⣿⣿⠟⣥⣾⣿⠎⡿⠿
⣿⡟⢰⣿⣿⣿⠏⣴⡿⠋⣼⡿⠋⣡⠆⢀⣤⣾⣿⣿⡿⠿⠿⠿⠿⠿⠿⠿⣿⣶⣌⡉⠀⠀⠀⠀⠀⠀⠀⣼⣿⣿⡿⢁⣾⣿⣿⢏⡜⢰⣷⡈⢻
⡟⢡⣿⣿⡿⠋⣼⡏⢂⣼⠟⠁⠀⣡⣶⣿⡿⢋⣩⣅⡀⠀⢀⣤⣶⣶⣦⡀⠈⠛⢿⣿⣦⠀⣠⣶⣦⠀⣸⣿⣿⡟⢱⣿⣿⡿⢣⣾⡇⢸⣿⡇⢢⠹⣿
⠇⣾⣿⡟⠁⣼⠞⠂⡾⠃⣠⠄⠰⠛⠉⡅⢄⠈⠉⣛⠛⠿⣿⣿⣿⠛⠉⠀⠀⠀⠀⠙⣿⣧⠈⠉⠁⠀⣿⣿⣿⠁⣿⣿⡿⢡⣿⣿⠇⣾⣿⡇⣼⢠⠘⣿
⠀⣿⣿⠁⢰⠿⠀⣸⠇⠘⠋⡀⠀⠁⠀⠀⠀⠀⠀⠀⠈⠁⠒⠬⢉⠻⠶⡄⠀⠀⠀⠀⢸⣿⣧⠀⠀⠀⢿⣿⣿⣠⣿⣿⢃⣿⣿⣿⢸⣿⣿⠇⣿⢳⡆ ⣿
⣇⢻⣿⠂⡀⠀⠁⠛⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⣄⠀⠀⠀⠀⣼⣿⣿⠀⢾⡇⢸⡿⣿⣿⣿⣿⠀⢿⡿⢃⣿⣿⡏⣸⡟⣸⠀ ⣿⣿
⣿⡌⢿⣶⣷⣈⣐⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀⣀⠀⠀⠀⠀⠀⠀⠁⠠⠀⠺⣿⣿⡿⠀⠀⠀⠸⡿⢿⣿⣿⣿⣄⣠⣴⣿⣿⠟⣴⡟⣰⡟⢰⣿
⣿⣷⣌⢻⣿⣿⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⣿⣷⣦⣄⠀⠀⠀⠀⠀⠀⠂⠈⠛⢡⣾⣦⠀⠀⠩⠍⢚⣿⣿⣿⣿⣿⣿⣥⣾⠏⣴⡿⢡⣿
⣿⣿⣿⣧⡙⠻⠐⠀⠀⠀⠀⠀⠀⠀⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣶⠆⠀⣴⣶⣶⡀⠀⠉⠉⠀⠀⠀⠈⢐⣄⣻⣿⣿⣿⣿⣿⣡⣾⡟⣡⣿
⣿⣿⣿⣿⣿⣶⡈⠀⠀⠀⠀⠀⢀⣼⣿⡿⠋⣉⣉⣹⠟⠉⠙⠻⣿⣿⣿⢀⣠⣄⡈⠹⣿⣷⠀⠀⠀⣰⢂⠢⠠⠿⠿⠉⠃⢋⠛⠋⢹⠿⢋⣴
⣿⣿⣿⣿⣿⣿⣿⡦⠄⠀⢤⣤⡈⠻⠟⢀⣾⣿⣿⣿⣷⠠⣶⣿⣿⠿⣿⣿⣿⡿⠿⠄⣈⣡⣧⠀⠀⢻⡘⢿⣦⠑⠈⠀⠀⠀⠈⢠⣤⣾
⣿⣿⣿⣿⣿⣿⠋⠀⠀⠀⣸⣿⣷⠘⠟⠛⢛⣿⣷⣌⠛⠁⠈⠛⢡⣾⣿⣿⣿⣥⣀⢀⡀⠉⣩⡀⠀⠀⣤⣤⣤⣀⠀⠀⠀⠀⢠⣿
⣿⣿⣿⣿⣿⢉⠀⠀⠀⢠⣿⣿⣿⣇⡘⢰⣿⣿⣿⣿⡇⢠⣈⠁⣸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠹⣿⣿⣿⣿⡄⠀⢀⣾
⣿⣿⣿⣿⣿⠀⠈⠗⣀⡘⠋⠋⠉⣉⣙⠒⢤⡙⠻⣿⡇⣾⣿⠂⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⠀⠀⠀⠈⢉⠹⠿⠃⣠⣿
⣿⣿⣿⣿⣿⣦⡀⢰⣿⣇⣀⣽⠈⢿⡿⢿⣶⣌⡓⢶⣄⣙⠻⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠋⠀⠀⠀⢀⣠⣴⣶⣿
⣿⣿⣿⣿⣿⣿⣿⣄⣙⣛⣫⡄⢧⠀⠀⠫⠉⠿⠿⠶⠌⠻⢿⣷⣤⡍⠛⠻⠿⠟⠫⢙⣀⠠⠤⠄⣀⠀⠀⢸⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡷⠘⣧⡀⠀⣤⠶⠤⠥⠄⣥⠄⠈⠿⠆⠤⢴⣦⣤⡀⠄⡀⠀⠀⠀⣿⡀⠀⠘⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠘⠿⢂⠀⠀⢀⠀⠬⠅⠂⡀⢀⡀⠐⢒⡂⠉⠛⢶⣌⠢⡀⠀⢻⡧⠀⠀⠘⣛⢻⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⢀⣾⡆⠀⠀⠄⣿⣇⠀⣀⣸⣿⣶⠍⠠⢀⠀⠃⠈⢦⡙⢷⣤⣀⣉⡐⠷⠀⢀⡙⣇⠻⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣅⠀⢠⡿⠁⠀⣰⡶⠀⢀⠻⣷⣄⡙⢿⣿⠀⠶⠾⢰⣄⠀⠀⠁⣼⣿⡿⠋⠁⢀⠀⠿⠇⣸⡄⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠀⣠⣾⡿⠁⠈⠀⠑⣂⣙⠻⠶⣬⣑⣀⠠⠿⠟⣛⡋⠀⠙⠋⠀⠀⡀⠐⢸⣛⣩⣤⣴
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⣰⣿⣿⠃⠀⠀⠀⢰⣿⣿⣿⣶⠖⠈⠭⠍⣉⡙⠋⢹⣴⣢⠀⠈⠘⠁⣤⣾
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠻⣿⡟⠀⠀⠀⠀⢠⣽⣿⣿⡟⠀⠀⠀⠉⣼⣿⠗⠀⢿⣿⠀⡄⠀⢀⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠰⣿⣿⡄⠀⠀⠀⠈⠛⠛⠛⠀⠀⠀⠀⠀⣿⣿⠃⠰⠀⠉⠀⠔⠲⠿⢿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠛⠁⠀⠀⠀⠀⠀⠀⠀⠀⣸⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣼⣿
"@
$Global:BaseJsonFoldersStructure = @"
{
    "src": {
        "{{ PYTHON_PROJECT_NAME }}": {},
    },
    "logs": {},
    "tests": {},
    "examples": {
        "sub_example1": {
            "sub_example11": {},
            "sub_example12": {
                "sub_example121": {},
            },
        },
        "sub_example2": {},
    }
    {{ PYTHON_PROJECT_SPHINX_FOLDER_STRUCTURE }}
}
"@
$Global:PythonProjectGitInitialCommitMessage = "[Init]"
$Global:PythonProjectGitDevBranchName = "DEV"
$Global:PythonProjectCondaPythonVersion = "3.10"
$Global:PythonProjectCondaEnvName = $PythonProjectName + "_D" + $PythonProjectCondaPythonVersion
#:#/ PROJECT #######################################################################################
'@


#+# PYKICK:CONFIG ##################################################################################
$PyKickVersion = "1.0.3"
$PyKickLogsFolder = "logs"
$PyKickSrcFolder = "src"
$PyKickSphinxJsonFolderStructure = @'
    ,
    "docs": {
        "build": {},
        "source": {
            "{{ PYTHON_PROJECT_NAME }}": {},
            "notes": {},
            "_static": {
                "css": {},
                "js": {}
            }
        }
    }
'@

$PyKickDocsFolder = "docs"
$PyKickDocsBuildFolder = "build"
$PyKickDocsSourceFolder = "source"
$PyKickDocsSourceNotesFolder = "notes"
$PyKickDocsSourceStaticFolder = "_static"
$PyKickDocsSourceStaticCssFolder = "css"
$PyKickDocsSourceStaticJsFolder = "js"
$PyKickColorError = "Red"
$PyKickColorSuccess = "Green"
$PyKickColorInfo = "Cyan"
$PyKickColorWarning = "Yellow"
$PyKickColorDefaultText = "White"
$PyKickColorDefaultOption = "DarkGray"
$PyKickLogo = @'
 
::::::::::..-:. ::-.::: . ::: .,-::::: ::: .
 `;;;```.;;;';;. ;;;;';;; .;;,.;;;,;;;'````' ;;; .;;,.
  `]]nnn]]' '[[,[[[' [[[[[/' [[[[[[ [[[[[/'
   $$$"" c$$" _$$$$, $$$$$$ _$$$$,
   888o ,8P"` "888"88o, 888`88bo,__,o,"888"88o,
   YMMMb mM" MMM "MMP"MMM "YUMMMMMP"MMM "MMP"
 
'@


function Initialize-PyKick {
    param (
        [string]$ConfigFilePath,
        [string]$DefaultConfig,
        [switch]$Reset
    )

    if (-not (Test-Path -Path $ConfigFilePath) -or $Reset) {
        Write-Host "Initializing the configuration file $PyKickConfigFile at $ConfigFilePath ..." -ForegroundColor $PyKickColorInfo
        $DefaultConfig | Out-File -FilePath $ConfigFilePath -Encoding UTF8
    }

    if ($Reset) {
        if ($PSVersionTable.PSVersion.Major -ge 7) {
            $pwshPath = (Get-Command pwsh).Source

            Start-Process $pwshPath -ArgumentList '-NoExit'
            Start-Sleep -Milliseconds 1337
            Exit
        } else {
            $PwshMsg1 = "PowerShell 7 not found or too old."
            $PwshMsg2 = "Please restart your PowerShell manually to let the configuration reset take effect."
            Write-Host "$PwshMsg1 $PwshMsg2" -ForegroundColor $PyKickColorInfo
        }
    }

    . $ConfigFilePath
}

$PyKickName = "pykick"
$ProfileDirectory = Split-Path -Parent $Profile
$PyKickConfigFile = "$PyKickName.conf.ps1"
$PyKickConfigFilePath = Join-Path -Path $ProfileDirectory -ChildPath $PyKickConfigFile
Initialize-PyKick -ConfigFilePath $PyKickConfigFilePath -DefaultConfig $PYKICK_CONF_PS1
#+#/ PYKICK:CONFIG #################################################################################


#?# TEMPLATES ######################################################################################
#*# REQUIREMENTS ###############################################################################
$PythonProjectRequirementsFile = "requirements.txt"
$PythonProjectRequirements = @'
# Install the latest versions with ~= to ensure compatibility.
# If any issues arise, use == to lock to a specific version.
# Below is my winning combination :
# build ~= 1.2.1
# rich ~= 13.9.4
# sphinx ~= 7.4.7
# sphinx_rtd_dark_mode ~= 1.3.0
# toml ~= 0.10.2
# typer ~= 0.13.1
build
rich
sphinx
sphinx_rtd_dark_mode
toml
typer
'@

#*#/ REQUIREMENTS ##############################################################################

#*# LICENSE ####################################################################################
$PythonProjectLicenseYear = (Get-Date).Year
$PythonProjectLicenseFile = "LICENSE.md"
$PythonProjectLicense = @"
MIT License
 
Copyright © • {{ PYTHON_PROJECT_LICENSE_YEAR }} • {{ PYTHON_PROJECT_AUTHOR }}
 
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"@

#*#/ LICENSE ###################################################################################

#*# CHANGELOG ##################################################################################
$PythonProjectChangelogFile = "CHANGELOG.md"
$PythonProjectChangelog = @'
# {{ PYTHON_PROJECT_NAME }} Changelog
 
All notable changes to this project will be documented in this file.
 
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/).
 
## [Unreleased]
### Added
- Description of what has been added.
 
### Changed
- Description of what has been changed.
 
### Removed
- Description of what has been removed.
 
## [1.0.0] - YYYY-MM-DD
### Added
- Initial release of your project.
- Initial functionalities.
'@

#*#/ CHANGELOG #################################################################################

#*# README #####################################################################################
$PythonProjectReadmeFile = "README.md"
$PythonProjectReadme = @'
|BuildStatus| |License|
 
<!-- uncomment and replace with your own badges/logo -->
<!-- p align="center"><img src="logo_{{ PYTHON_PROJECT_NAME }}.png" alt="{{ PYTHON_PROJECT_NAME }}" width="256"></p -->
 
# 📦 {{ PYTHON_PROJECT_NAME }}
 
Description of **{{ PYTHON_PROJECT_NAME }}** 😁
 
## 💻 Installation
 
### Download and install from PyPi using pip (recommended)
 
```bash
python -m pip install --upgrade pip
pip install {{ PYTHON_PROJECT_NAME }}
```
 
### (Alternative) Manual install from Git
 
**Option 1 - Use pip to install straight from Github**
 
```bash
pip install git+https://github.com/<USER>/{{ PYTHON_PROJECT_NAME }}
```
**Option 2 - Clone and install manually**
 
```bash
# Clone the repository from Github
git clone https://github.com/<USER>/{{ PYTHON_PROJECT_NAME }}
cd {{ PYTHON_PROJECT_NAME }}
 
# RECOMMENDED MANUAL INSTALL METHOD
# Use pip to install the source code
pip install .
 
# ALTERNATIVE MANUAL INSTALL METHOD
# If you don't have pip, or have issues with installing using it, then you can use setuptools instead.
python -m build
pip install ./dist/{{ PYTHON_PROJECT_NAME }}-{{ PYTHON_PROJECT_VERSION }}.tar.gz
```
 
## 📘 Documentation (sadly yeah... 🤪)
 
..to do...
 
## ❤️ Thanks
 
..to do...
 
## 🔨 Todo
 
..to do...
 
## ©️ License
 
<!-- uncomment if only a badge with link is needed -->
<!--
[![Static Badge](https://img.shields.io/badge/licence-MIT-blue.svg)](https://opensource.org/licenses/MIT)
 
Copyright © • {{ PYTHON_PROJECT_LICENSE_YEAR }} • {{ PYTHON_PROJECT_AUTHOR }}
-->
 
{{ PYTHON_PROJECT_LICENSE }}
'@

#*#/ README ####################################################################################

#*# PROJECT.TOML ###############################################################################
$PythonProjectTomlFile = "pyproject.toml"
$PythonProjectToml = @"
[build-system]
requires = [
    "setuptools >= 75.0.0",
    "wheel",
]
build-backend = "setuptools.build_meta"
 
[project]
name = "{{ PYTHON_PROJECT_NAME }}"
authors = [
    {name = "{{ PYTHON_PROJECT_AUTHOR }}", email = "{{ PYTHON_PROJECT_AUTHOR_EMAIL }}"},
]
maintainers = [
    {name = "{{ PYTHON_PROJECT_AUTHOR }}", email = "{{ PYTHON_PROJECT_AUTHOR_EMAIL }}"},
]
description = "{{ PYTHON_PROJECT_DESCRIPTION }}"
readme = {file = "README.md", content-type = "text/markdown"}
license = {file = "LICENSE.md", content-type = "text/markdown"}
keywords = ["{{ PYTHON_PROJECT_NAME }}", ]
dynamic = [
    "version",
    "dependencies",
    "optional-dependencies",
]
classifiers = [
    "Development Status :: 2 - Pre-Alpha",
    "Intended Audience :: End Users/Desktop",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.10",
]
 
[project.urls]
#Homepage = "https://{{ PYTHON_PROJECT_NAME }}.io"
#Documentation = "https://..."
#Repository = "https://github.com/...git"
#"Bug Tracker" = "https://github.com/.../issues"
#Changelog = "https://github.com/.../blob/master/CHANGELOG.md"
 
[tool.setuptools.dynamic]
version = {attr = "{{ PYTHON_PROJECT_NAME }}.meta.__version__"}
dependencies = {file = ["requirements.txt"]}
 
[tool.setuptools.packages.find]
where = ["src"]
include = ["{{ PYTHON_PROJECT_NAME }}*"]
exclude = [
    "docs*",
    "examples*",
    "resources*",
    "tests*",
]
 
[project.entry-points."{{ PYTHON_PROJECT_NAME }}"]
{{ PYTHON_PROJECT_NAME }} = "{{ PYTHON_PROJECT_NAME }}.__main__:main"
 
[tool.setuptools.package-data]
{{ PYTHON_PROJECT_NAME }} = ["*.conf.toml"]
 
"@

#*#/ PROJECT.TOML ##############################################################################

#*# GITIGNORE ##################################################################################
$PythonProjectGitIgnoreFile = ".gitignore"
$PythonProjectGitIgnore = @'
# Logs and temporary files
log/
logs/
*.log
*.swp
*.key
/.env
/.env.*
.idea/
.vscode/
__pycache__/
 
# PyPi build files
.coverage
build
dist
*.egg-info
 
# Local development files
/venv/
/venv_*/
/dev_*.py
/test_*.py
/t_*.py
/*.sqlite*
/*.db
/out*
 
# Additional files to consider
*.py[cod]
*.so
*.dll
*.dylib
.coverage.*
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.ipynb_checkpoints
'@

#*#/ GITIGNORE #################################################################################

#*# PROJECT:__INIT__.PY ########################################################################
$PythonProjectInitFile = "__init__.py"
$PythonProjectInit = @'
"""
{{ PYTHON_PROJECT_ASCII_LOGO }}
{{ PYTHON_PROJECT_NAME }} package
"""
 
'@

#*#/ PROJECT:__INIT__.PY #######################################################################

#*# PROJECT:__MAIN__.PY ########################################################################
$PythonProjectMainFile = "__main__.py"
$PythonProjectMain = @'
from {{ PYTHON_PROJECT_NAME }} import cli
 
 
def main() -> None:
    cli.app()
 
 
if __name__ == "__main__":
    main()
 
'@

#*#/ PROJECT:__MAIN__.PY #######################################################################

#*# PROJECT:META.PY ############################################################################
$PythonProjectMetaFile = "meta.py"
$PythonProjectMeta = @'
__logo__ = ("""
{{ FRM }}{{ PYTHON_PROJECT_ASCII_LOGO }}
""".replace("{{ FRM }}", "[bright_black]"))
 
__app_name__ = "{{ PYTHON_PROJECT_NAME }}"
__version__ = "{{ PYTHON_PROJECT_VERSION }}"
__description__ = "{{ PYTHON_PROJECT_DESCRIPTION }}"
__author__ = "{{ PYTHON_PROJECT_AUTHOR }}"
__email__ = "{{ PYTHON_PROJECT_AUTHOR_EMAIL }}"
__url__ = "https://{{ PYTHON_PROJECT_NAME }}.io"
__keywords__ = [ "{{ PYTHON_PROJECT_NAME }}" ]
__classifiers__ = [
    'Development Status :: 2 - Pre-Alpha',
    'Intended Audience :: End Users/Desktop',
    'License :: OSI Approved :: MIT License',
    'Programming Language :: Python :: 3',
    'Programming Language :: Python :: 3.10',
]
__license_type__ = "MIT"
__license__ = """
{{ PYTHON_PROJECT_LICENSE }}
"""
'@

#*#/ PROJECT:META.PY ###########################################################################

#*# PROJECT:CLI.PY #############################################################################
$PythonProjectCliFile = "cli.py"
$PythonProjectCli = @'
from typing import Optional
 
import typer
from rich import print
from rich.console import Console
from rich.table import Table
 
from {{ PYTHON_PROJECT_NAME }} import meta
 
app = typer.Typer(add_completion=False)
console = Console()
 
def _version_callback(value: bool) -> None:
    if value:
        print(f"[light_salmon1]{meta.__app_name__}[/] v{meta.__version__}")
        raise typer.Exit()
 
@app.callback()
def main(
    version: Optional[bool] = typer.Option(
        None,
        "--version",
        "-v",
        help="Show the application's version and exit.",
        callback=_version_callback,
        is_eager=True,
    )
) -> None:
    return
 
@app.command()
def info(
    full: bool = typer.Option(
        False,
        "--full",
        "-f",
        help="Show full information about the application.",
    ),
) -> None:
    print(meta.__logo__)
 
    if full:
        _data = [
            ("Name", meta.__app_name__),
            ("Version", meta.__version__),
            ("Description", meta.__description__),
            ("Author", meta.__author__),
            ("Email", meta.__email__),
            ("URL", meta.__url__),
            ("Keywords", ", ".join(meta.__keywords__)),
            ("Classifiers", "\n".join(meta.__classifiers__)),
            ("License Type", meta.__license_type__),
            ("License", meta.__license__),
            ("", ""),
        ]
 
        table = Table(show_header=False, show_lines=False, title=None, box=None)
        table.add_column(justify="right")
        table.add_column(justify="left")
 
        for row in _data:
            table.add_row(f"[light_salmon1]{row[0]}[/]", row[1])
 
        console.print(table)
 
        return
 
    _version_callback(True)
 
{{ PYTHON_PROJECT_CLI_CHOPPER }}
 
 
if __name__ == "__main__":
    app()
 
'@

$PythonProjectCliChopper = @'
@app.command()
def quote() -> None:
    import random
 
    quote = random.choice([
    """I realized that back then, the reason I wanted to become human, was that I really just wanted to have friends.
    Now, I just want to be a monster that can help Luffy.""",
    "I'm gonna try even harder and be helpful to everyone!",
    "I gotta give my all for everyone in my crew!",
    "Bastard! I'm not losing this!",
    "Robin is a part of our crew! I'm going to give it to anyone who hurts my crew!",
    "I will be even more dependable!",
    "T-this is nothing!",
    "Alright! Let's do this!",
    "I want to be the sort of man people can rely on!",
    "Hey! I did it!",
    "I won...? Against the Seven Warlords of the Sea?! I'm amazing!"
])
    bubble = f"""
   { '-' * (len(quote) + 2) }
  ( {quote} )
   { '-' * (len(quote) + 2) }
      \\
    """
    print(f"[light_sky_blue1]{bubble}[/]")
    print(meta.__logo__)
'@

#*#/ PROJECT:CLI.PY ############################################################################

#*# PROJECT:CONF.TOML ##########################################################################
$PythonProjectConfTomlFile = "conf.toml"
$PythonProjectConfToml = @'
{{ PYTHON_PROJECT_ASCII_LOGO }}
[app]
name = "{{ PYTHON_PROJECT_NAME }}"
'@

#*#/ PROJECT:CONF.TOML #########################################################################

#*# SPHINX:MAKEFILE ############################################################################
$PythonProjectSphinxMakefileFile = "Makefile"
$PythonProjectSphinxMakefile = @'
# Minimal makefile for Sphinx documentation
#
 
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
 
# Put it first so that "make" without argument is like "make help".
help:
    @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
 
.PHONY: help Makefile
 
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
    @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
'@

#*#/ SPHINX:MAKEFILE ###########################################################################

#*# SPHINX:MAKE.BAT ############################################################################
$PythonProjectSphinxMakeBatFile = "make.bat"
$PythonProjectSphinxMakeBat = @'
@ECHO OFF
 
pushd %~dp0
 
REM Command file for Sphinx documentation
 
if "%SPHINXBUILD%" == "" (
    set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
 
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
    echo.
    echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
    echo.installed, then set the SPHINXBUILD environment variable to point
    echo.to the full path of the 'sphinx-build' executable. Alternatively you
    echo.may add the Sphinx directory to PATH.
    echo.
    echo.If you don't have Sphinx installed, grab it from
    echo.https://www.sphinx-doc.org/
    exit /b 1
)
 
if "%1" == "" goto help
 
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
 
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
 
:end
popd
'@

#*#/ SPHINX:MAKE.BAT ###########################################################################

#*# SPHINX:CONF.PY #############################################################################
$PythonProjectSphinxConfPyFile = "conf.py"
$PythonProjectSphinxConfPy = @'
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
 
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
 
project = '{{ PYTHON_PROJECT_NAME }}'
copyright = '{{ PYTHON_PROJECT_LICENSE_YEAR }}, {{ PYTHON_PROJECT_AUTHOR }}'
author = '{{ PYTHON_PROJECT_AUTHOR }}'
release = '{{ PYTHON_PROJECT_VERSION }}'
 
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
 
extensions = [
    'sphinx.ext.autodoc',
    'sphinx.ext.autosummary',
    'sphinx.ext.intersphinx',
    'sphinx.ext.viewcode',
    'sphinx_rtd_dark_mode',
]
 
templates_path = ['_templates']
exclude_patterns = ['_build']
 
 
 
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
 
html_theme = 'sphinx_rtd_theme'
html_static_path = ['_static']
 
html_css_files = ['css/{{ PYTHON_PROJECT_NAME }}.css']
html_js_files = ['js/{{ PYTHON_PROJECT_NAME }}.js']
 
pygments_style = 'monokai'
highlight_language = 'python3'
 
default_dark_mode = False
 
#html_logo = 'https://github.com/KaminoU/assets/blob/main/pykick/{{ PYKICK_NAME }}.png'
html_logo = '{{ PYKICK_NAME }}.png'
html_theme_options = {
    'navigation_depth': 7,
    'collapse_navigation': False,
    'style_nav_header_background': '#3F3B3A',
}
 
autosummary_generate = True
autosummary_generate_overwrite = False
autodoc_default_options = {
    'members': True,
    'undoc-members': True
}
'@

#*#/ SPHINX:CONF.PY ############################################################################

#*# SPHINX:PYKICK.PNG ##########################################################################
$PythonProjectSphinxPyKickPngFile = "pykick.png"
$PythonProjectSphinxPyKickPng = @'
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
'@

#*#/ SPHINX:PYKICK.PNG #########################################################################

#*# SPHINX:BR.RST ##############################################################################
$PythonProjectSphinxBrRstFile = "br.rst"
$PythonProjectSphinxBrRst = @'
.. raw:: html
 
   <br /><br />
'@

#*#/ SPHINX:BR.RST #############################################################################

#*# SPHINX:INDEX.RST ###########################################################################
$PythonProjectSphinxIndexRstFile = "index.rst"
$PythonProjectSphinxIndexRst = @'
.. {{ PYTHON_PROJECT_NAME }} documentation master file, created by
   pykick on {{ PYKICK_GENERATION_DATE }} (based on Sphinx, see Sphinx-quickstart documentation for more details).
   You can adapt this file completely to your liking, but it should at least
   contain the root `toctree` directive.
 
{{ PYTHON_PROJECT_NAME }} Documentation
{{ UNDERLINES_CHAR }}
 
.. include:: br.rst
.. include:: notes/badges.rst
.. include:: br.rst
 
.. include:: br.rst
.. include:: notes/logo.rst
.. include:: br.rst
 
.. include:: br.rst
.. include:: notes/welcome.rst
.. include:: br.rst
 
.. include:: br.rst
.. include:: notes/install.rst
.. include:: br.rst
 
.. include:: br.rst
Python Module Overview
======================
 
Below is a listing of the modules available in ``{{ PYTHON_PROJECT_NAME }}`` with a short description of what each module contains.
 
.. include:: {{ PYTHON_PROJECT_NAME }}/index.rst
.. include:: br.rst
 
.. include:: br.rst
All Documentation
=================
 
.. toctree::
   :maxdepth: 3
   :caption: Main:
 
   notes/install
.. include:: br.rst
 
.. include:: br.rst
.. toctree::
   :maxdepth: 3
   :caption: Code Documentation:
 
   {{ PYTHON_PROJECT_NAME }}/{{ PYTHON_PROJECT_NAME }}.cli
.. include:: br.rst
 
.. include:: br.rst
.. include:: reflinks.rst
.. include:: br.rst
 
.. include:: br.rst
Indices and tables
==================
 
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
'@

#*#/ SPHINX:INDEX.RST ##########################################################################

#*# SPHINX:REFLINKS.RST ########################################################################
$PythonProjectSphinxReflinksRstFile = "reflinks.rst"
$PythonProjectSphinxReflinksRst = @'
Useful links
============
 
.. _reflinks:
 
.. note::
 
    This section contains a list of useful links. So please, use and abuse all the docs, it is refreshing, helpful and also helps fall asleep ... =P
 
* |python_style_guide|
* |python_url|
 
.. |python_style_guide| raw:: html
 
   <a href="https://www.python.org/dev/peps/pep-0008/" target="_blank">PEP 8 — Style Guide for Python Code</a>
 
.. |python_url| raw:: html
 
   <a href="https://www.python.org" target="_blank">Python home page</a>
'@

#*#/ SPHINX:REFLINKS.RST #######################################################################

#*# SPHINX:PROJECT.INDEX.RST ###################################################################
$PythonProjectSphinxProjectIndexRstFile = "index.rst"
$PythonProjectSphinxProjectIndexRst = @'
.. autosummary::
 
    {{ PYTHON_PROJECT_NAME }}.cli
'@

#*#/ SPHINX:PROJECT.INDEX.RST ##################################################################

#*# SPHINX:PROJECT.MODULES.RST #################################################################
$PythonProjectSphinxProjectModulesRstFile = ".cli.rst"
$PythonProjectSphinxProjectModulesRst = @'
{{ PYTHON_PROJECT_NAME }}.cli
{{ UNDERLINES_CHAR }}
 
.. automodule:: {{ PYTHON_PROJECT_NAME }}.cli
    :members:
    :undoc-members:
    :show-inheritance:
'@

#*#/ SPHINX:PROJECT.MODULES.RST ################################################################

#*# SPHINX:NOTES.BADGES.RST ####################################################################
$PythonProjectSphinxNotesBadgesRstFile = "badges.rst"
$PythonProjectSphinxNotesBadgesRst = @'
.. image:: https://img.shields.io/badge/licence-MIT-blue.svg
   :alt: Licence MIT
   :target: https://opensource.org/licenses/MIT
 
.. image:: https://img.shields.io/badge/github-{{ PYTHON_PROJECT_NAME }}-orange.svg
   :alt: git homepage
   :target: https://github.com/KaminoU/{{ PYTHON_PROJECT_NAME }}
 
.. image:: https://img.shields.io/badge/pypi-v1.0.0-green.svg
   :alt: {{ PYTHON_PROJECT_NAME }} v1.0.0
   :target: https://pypi.org/project/{{ PYTHON_PROJECT_NAME }}/1.0.0/
 
.. image:: https://img.shields.io/badge/readthedocs-{{ PYTHON_PROJECT_NAME }}-green.svg
   :alt: {{ PYTHON_PROJECT_NAME }} documentations
   :target: https://{{ PYTHON_PROJECT_NAME }}.readthedocs.io/en/latest/index.html
'@

#*#/ SPHINX:NOTES.BADGES.RST ###################################################################

#*# SPHINX:NOTES.LOGO.RST ######################################################################
$PythonProjectSphinxNotesLogoRstFile = "logo.rst"
$PythonProjectSphinxNotesLogoRst = @'
.. alternatively, you can use local file saved in the _static folder _static/{{ PYTHON_PROJECT_NAME }}.png
.. image:: https://raw.githubusercontent.com/KaminoU/assets/refs/heads/main/pykick/pykick.png
   :width: 384px
   :alt: {{ PYTHON_PROJECT_NAME }} Logo
   :align: center
'@

#*#/ SPHINX:NOTES.LOGO.RST #####################################################################

#*# SPHINX:NOTES.WELCOME.RST ###################################################################
$PythonProjectSphinxNotesWelcomeRstFile = "welcome.rst"
$PythonProjectSphinxNotesWelcomeRst = @'
**Welcome!** =}
---------------
 
This is {{ PYTHON_PROJECT_NAME }}. I have absolutely no idea what I'm doing... But it works, so I'm sharing it with you.
 
o( ^ ^ )o Cheers, and may the code be with you... o( ^ ^ )o
 
**A dev** ^^
'@

#*#/ SPHINX:NOTES.WELCOME.RST ##################################################################

#*# SPHINX:NOTES.INSTALL.RST ###################################################################
$PythonProjectSphinxNotesInstallRstFile = "install.rst"
$PythonProjectSphinxNotesInstallRst = @'
Installation
============
 
Download and install from PyPi using pip (recommended)
------------------------------------------------------
 
.. code-block:: bash
 
    pip install {{ PYTHON_PROJECT_NAME }}
 
 
(Alternative) Manual install from Git
--------------------------------------
 
**Option 1 - Use pip to install directly from GitHub**
 
.. code-block:: bash
 
    pip install git+https://github.com/<USER>/{{ PYTHON_PROJECT_NAME }}.git
 
 
**Option 2 - Clone and install manually**
 
.. code-block:: bash
 
    # Clone the repository from GitHub
    git clone https://github.com/<USER>/{{ PYTHON_PROJECT_NAME }}.git
    cd /to/the/{{ PYTHON_PROJECT_NAME }}/location
 
    # RECOMMENDED MANUAL INSTALL METHOD
    # Use pip to install the source code
    pip install .
 
    # ALTERNATIVE MANUAL INSTALL METHOD
    # If you don't have pip, or have issues with it, you can use setuptools instead.
    python -m build
    pip install ./dist/{{ PYTHON_PROJECT_NAME }}-{{ PYTHON_PROJECT_VERSION }}.tar.gz
'@

#*# SPHINX:NOTES.INSTALL.RST ###################################################################

#*# SPHINX:_STATIC.CSS #########################################################################
$PythonProjectSphinxStaticCssFile = ".css"
$PythonProjectSphinxStaticCss = @'
@import url("theme.css");
 
dd {
    margin-top: 1.3em !important;
}
 
dt .sig.sig-object.py {
    margin-top: 1.1em !important;
}
 
.wy-nav-content {
    max-width: 1200px !important;
}
 
li.toctree-l4 li.toctree-l5 > a {
    display: none;
}
 
li.toctree-l5.current > a {
    display: block;
}
 
.wy-menu-vertical li.toctree-l4.current li.toctree-l5 > a {
    display: block;
    background: #bdbdbd;
    padding: .4045em 6em;
}
 
.default_value .pre {
  color: magenta;
}
 
p .reference.internal .pre,
.sig-prename.descclassname .pre,
.sig-name.descname .pre,
.sig-return-typehint .pre {
  color: #f7746f;
}
 
cite {
    color: #132a3a;
    background-color: #29ce64;
}
'@

#*#/ SPHINX:_STATIC.CSS ########################################################################

#*# SPHINX:_STATIC.JS ##########################################################################
$PythonProjectSphinxStaticJsFile = ".js"
$PythonProjectSphinxStaticJs = @'
$(document).ready(function () {
    $('a.external').attr('target', '_blank');
});
'@

#*#/ SPHINX:_STATIC.JS #########################################################################
#?#/ TEMPLATES #####################################################################################


#+# PYKICK #########################################################################################
if (Test-Path Variable:\IsWindows) { Remove-Variable IsWindows -Force -ErrorAction SilentlyContinue }
if (Test-Path Variable:\IsMacOS) { Remove-Variable IsMacOS -Force -ErrorAction SilentlyContinue }
if (Test-Path Variable:\IsLinux) { Remove-Variable IsLinux -Force -ErrorAction SilentlyContinue }

$IsWindows = $false
$IsMacOS = $false
$IsLinux = $false

if ($PSVersionTable.PSEdition -eq 'Core') {
    switch ($env:OSTYPE) {
        { $_ -like 'darwin*' } { $IsMacOS = $true }
        { $_ -like 'linux*' } { $IsLinux = $true }
        default { $IsWindows = $true }
    }
} else {
    $IsWindows = $true
}


function Show-Banner {
    $Colors = @('Cyan', 'DarkGray', 'DarkGray', 'DarkCyan', 'Blue', 'DarkBlue')
    $Lines = $PyKickLogo -split "`n"
    $ColorIndex = 0

    Clear-Host
    foreach ($Line in $Lines) {
        if ($Line.Trim() -ne '') {
            Write-Host $Line -ForegroundColor $Colors[$ColorIndex]
            $ColorIndex = ($ColorIndex + 1) % $Colors.Length
        } else {
            Write-Host $Line
        }
    }
}

function Update-Holders {
    param (
        [string]$Content,
        [hashtable]$Placeholders
    )

    foreach ($Key in $Placeholders.Keys) {
        $Content = $Content -replace [regex]::Escape($Key), $Placeholders[$Key]
    }

    return $Content
}

function New-PyKickPng {
    param (
        [string]$Path
    )

    Write-Host "Generating $PyKickName.png at $Path ..." -ForegroundColor $PyKickColorInfo

    $AbsolutePath = Resolve-Path -Path $Path
    $PyKickPngFilePath = Join-Path -Path $AbsolutePath -ChildPath $PythonProjectSphinxPyKickPngFile
    Write-Host "Writing $PyKickPngFilePath ..." -ForegroundColor $PyKickColorInfo
    $PyKickB64Png = ($PythonProjectSphinxPyKickPng -join "`n").Trim()
    Write-Host "Converting base64 to png ..." -ForegroundColor $PyKickColorInfo
    $PyKickPng = [System.Convert]::FromBase64String($PyKickB64Png)
    Write-Host "Writing png to $PyKickPngFilePath ..." -ForegroundColor $PyKickColorInfo
    [System.IO.File]::WriteAllBytes($PyKickPngFilePath, $PyKickPng)
}

function New-PyProjectFile {
    param (
        [string]$FileName,
        [string]$Path,
        [hashtable]$Placeholders = @{},
        [string]$Content
    )

    Write-Host "Generating $FileName at $Path ..." -ForegroundColor $PyKickColorInfo

    $FilePath = Join-Path -Path $Path -ChildPath $FileName
    if ($Placeholders.Count -gt 0) {
        $ProcessedContent = Update-Holders -Content $Content -Placeholders $Placeholders
        $ProcessedContent | Out-File -FilePath $FilePath -Encoding utf8
    } else {
        $Content | Out-File -FilePath $FilePath -Encoding utf8
    }
}

function Test-SphinxTreeStructure {
    param (
        [string[]]$Paths,
        [string]$CombinedJsonFoldersStructure,
        [hashtable]$Placeholders
    )

    foreach ($Path in $Paths) {
        if (-not (Test-Path -Path $Path)) {
            Write-Host ""
            Show-FormattedMessage -MessagesAndColors @(
                @{"Error: The Sphinx documentation tree is not correct, your current tree is " = $PyKickColorError}
            )
            Write-Host ""
            Show-Tree -JsonStructure $(Update-Holders `
                -Content $CombinedJsonFoldersStructure `
                -Placeholders $Placeholders)
            Write-Host ""
            Write-Host "Expected Sphinx documentation tree structure:" -ForegroundColor $PyKickColorInfo
            foreach ($p in $Paths) {
                Write-Host $p
            }

            return $false
        }
    }

    return $true
}

function Set-HomeDirectory {
    $HomeDir = [System.Environment]::GetFolderPath('UserProfile')
    Set-Location -Path $HomeDir
}

function Restore-Changes {
    param (
        [string]$Path
    )

    Set-HomeDirectory
    Write-Host ""
    Write-Host "Reverting the changes ..." -ForegroundColor $PyKickColorError
    Show-FormattedMessage -MessagesAndColors @(
        @{"Removing the directory " = $PyKickColorError},
        @{$Path = $PyKickColorDefaultText}
    )
    
    Write-Host ""
    try {
        Remove-Item -Path $Path -Recurse -Force
        Show-FormattedMessage -MessagesAndColors @(
            @{"The directory " = $PyKickColorSuccess},
            @{$Path = $PyKickColorDefaultText},
            @{" and its contents have been successfully removed." = $PyKickColorSuccess}
        )
    } catch {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: Unable to remove the directory " = $PyKickColorError},
            @{$Path = $PyKickColorDefaultText},
            @{" and its contents. Please check your permissions and remove the directory manually." = $PyKickColorError}
        )
    }
}

function New-NewFolderStructure {
    param (
        [string]$RootPath,
        [string]$FolderStructureJson,
        [hashtable]$Placeholders,
        [switch]$Sphinx
    )

    if ($Sphinx) {
        Write-Host "Generating folders with Sphinx documentation structure at $RootPath ..." -ForegroundColor $PyKickColorInfo
    } else {
        Write-Host "Generating folder structure at $RootPath ..." -ForegroundColor $PyKickColorInfo
    }

    $FolderStructure = $(Update-Holders -Content $FolderStructureJson -Placeholders $Placeholders) | ConvertFrom-Json

    function New-Folders {
        param (
            [string]$CurrentPath,
            [pscustomobject]$Structure
        )

        foreach ($Key in $Structure.PSObject.Properties.Name) {
            $folderPath = Join-Path -Path $CurrentPath -ChildPath $Key
            if (-not (Test-Path -Path $folderPath)) {
                New-Item -Path $folderPath -ItemType Directory | Out-Null
            }
            New-Folders -CurrentPath $folderPath -Structure $Structure.$Key
        }
    }

    New-Folders -CurrentPath $RootPath -Structure $FolderStructure
}

function ConvertTo-Hashtable {
    param (
        [Parameter(Mandatory=$true)]
        [object]$PSCustomObject
    )

    $hashtable = @{}
    foreach ($property in $PSCustomObject.PSObject.Properties) {
        if ($property.Value -is [System.Management.Automation.PSObject]) {
            $hashtable[$property.Name] = ConvertTo-Hashtable -PSCustomObject $property.Value
        } else {
            $hashtable[$property.Name] = $property.Value
        }
    }
    return $hashtable
}

function Show-Tree {
    param (
        [Parameter(Mandatory=$true)]
        [string]$JsonStructure
    )

    function Print-Tree {
        param (
            [string]$Prefix,
            [hashtable]$Node
        )

        foreach ($Key in $Node.Keys) {
            Write-Host "$Prefix+-- $Key" -ForegroundColor $PyKickColorInfo
            if ($Node[$Key] -is [hashtable]) {
                Print-Tree "$Prefix| " $Node[$Key]
            }
        }
    }

    Print-Tree "" $(ConvertTo-Hashtable -PSCustomObject $($JsonStructure | ConvertFrom-Json))
}

function Show-FormattedMessage {
    param (
        [hashtable[]]$MessagesAndColors
    )

    foreach ($item in $MessagesAndColors) {
        foreach ($Key in $item.Keys) {
            $message = $Key
            $color = $item[$Key]
            Write-Host $message -ForegroundColor $color -NoNewline
        }
    }
    Write-Host ""
}

function Initialize-GitRepo {
    param (
        [string]$Path,
        [string]$InitialCommit,
        [string]$BranchName,
        [switch]$Silent
    )

    Write-Host "Initializing Git repository at $Path ..." -ForegroundColor $PyKickColorInfo

    function Invoke-GitCommand {
        param (
            [string]$Command,
            [string[]]$Arguments,
            [string]$Color = $PyKickColorInfo,
            [switch]$Silent
        )

        $GitCommand = "git $Command $($Arguments -join ' ')"
        $Output = Invoke-Expression -Command $GitCommand 2>&1

        if (-not $Silent) {
            foreach ($Line in $Output -split "`n") {
                Write-Host $Line -ForegroundColor $Color
            }
        }
    }

    Push-Location -Path $Path

    Invoke-GitCommand -Command "init" -Silent:$Silent
    Invoke-GitCommand -Command "add" -Arguments "." -Silent:$Silent
    Invoke-GitCommand -Command "commit" -Arguments @("-m", "`"$InitialCommit`"") -Silent:$Silent
    Invoke-GitCommand -Command "branch" -Arguments "$BranchName" -Silent:$Silent
    Invoke-GitCommand -Command "checkout" -Arguments "$BranchName" -Silent:$Silent

    Pop-Location
}

function Test-Schema {
    param (
        [string]$Value,
        [string]$Schema
    )

    switch ($Schema) {
        'PythonProjectName' {
            return $Value -match '^[a-z0-9_]+$'
        }
        'Year' {
            $CurrentYear = (Get-Date).Year
            return $Value -match '^\d{4}$' -and [int]$Value -ge $CurrentYear
        }
        'Email' {
            return $Value -match '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        }
        default {
            throw "Unknown schema: $Schema"
        }
    }
}

function Show-ResetOption {
    Write-Host ""
    Show-FormattedMessage -MessagesAndColors @(
        @{"You can use the option" = $PyKickColorInfo},
        @{" -Reset" = $PyKickColorDefaultOption},
        @{" to reset the config file." = $PyKickColorInfo}
    )
}

function Test-BaseJsonFoldersStructure {
    param (
        [string]$JsonStructure
    )

    $JsonStructureSrcName = "{{ PYTHON_PROJECT_NAME }}"
    $JsonStructureSrcSphinx = "{{ PYTHON_PROJECT_SPHINX_FOLDER_STRUCTURE }}"

    if ($JsonStructure -notmatch "{{\s+PYTHON_PROJECT_NAME\s+}}" `
            -or $JsonStructure -notmatch "{{\s+PYTHON_PROJECT_SPHINX_FOLDER_STRUCTURE\s+}}") {
        Write-Host ""
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: The base JSON structure is not correct. " = $PyKickColorError},
            @{"Please make sure that the placeholders " = $PyKickColorError},
            @{$JsonStructureSrcName = $PyKickColorDefaultText},
            @{" and " = $PyKickColorError},
            @{$JsonStructureSrcSphinx = $PyKickColorDefaultText},
            @{" are present in the JSON structure." = $PyKickColorError}
        )
        Show-ResetOption

        return $false
    }

    return $true
}

function Test-JsonStructure {
    param (
        [string]$JsonStructure
    )

    try {
        $JsonStructure | ConvertFrom-Json | Out-Null

        return $true
    } catch {

        Write-Host ""
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: The variable" = $PyKickColorError},
            @{' $BaseJsonFoldersStructure' = $PyKickColorDefaultText},
            @{" is not a valid JSON structure." = $PyKickColorError},
            @{" Its current value is:" = $PyKickColorError}
        )
        Write-Host $JsonStructure -ForegroundColor $PyKickColorDefaultText
        Write-Host $_.Exception.Message -ForegroundColor $PyKickColorError
        Show-ResetOption

        return $false
    }
}

function New-CondaEnv {
    param (
        [string]$EnvName,
        [string]$PythonVersion,
        [string]$RequirementsFilePath,
        [string]$Path,
        [switch]$Silent
    )
    Write-Host "Creating Conda environment $EnvName with Python $PythonVersion ..." -ForegroundColor $PyKickColorInfo

    $LogsFolder = Join-Path -Path $Path -ChildPath $PyKickLogsFolder
    if (-not (Test-Path -Path $LogsFolder)) {
        New-Item -ItemType Directory -Path $LogsFolder | Out-Null
    }

    $CondaOutputFile = "$LogsFolder/conda_output.txt"
    $CondaErrorFile = "$LogsFolder/conda_error.txt"
    $PipOutputFile = "$LogsFolder/pip_output.txt"
    $PipErrorFile = "$LogsFolder/pip_error.txt"

    if ($Silent) {
        Start-Process -FilePath conda -ArgumentList "create --name $EnvName python=$PythonVersion -y" `
        -NoNewWindow -Wait -RedirectStandardOutput $CondaOutputFile -RedirectStandardError $CondaErrorFile
    } else {
        $Output = conda create --name $EnvName python=$PythonVersion -y 2>&1
        foreach ($Line in $Output -split "`n") {
            Write-Host $Line -ForegroundColor $PyKickColorInfo
        }
    }

    & conda activate $EnvName

    if (Test-Path $RequirementsFilePath) {
        if ($Silent) {
            Start-Process -FilePath conda -ArgumentList "run -n $EnvName pip install -r $RequirementsFilePath" `
            -NoNewWindow -Wait -RedirectStandardOutput $PipOutputFile -RedirectStandardError $PipErrorFile
        } else {
            $PipOutput = & conda run -n $EnvName pip install -r $RequirementsFilePath 2>&1
            foreach ($Line in $PipOutput -split "`n") {
                Write-Host $Line -ForegroundColor $PyKickColorInfo
            }
        }
    } else {
        Write-Host "$PythonProjectRequirementsFile not found at $RequirementsFilePath" -ForegroundColor $PyKickColorWarning
    }
}

function Restore-Conda {
    param (
        [string]$EnvName
    )

    Write-Host ""
    Write-Host "Reverting Conda environment changes..." -ForegroundColor $PyKickColorError
    
    try {
        conda deactivate
    } catch {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: Unable to deactivate Conda environment " = $PyKickColorError},
            @{$EnvName = $PyKickColorDefaultText},
            @{"." = $PyKickColorError}
        )
    }

    try {
        conda remove --name $EnvName --all --yes
        Show-FormattedMessage -MessagesAndColors @(
            @{"Conda environment " = $PyKickColorSuccess},
            @{$EnvName = $PyKickColorDefaultText},
            @{" has been successfully removed." = $PyKickColorSuccess}
        )
    } catch {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: Unable to remove Conda environment " = $PyKickColorError},
            @{$EnvName = $PyKickColorDefaultText},
            @{"." = $PyKickColorError}
        )
    }
}

function Import-Logo {
    param (
        [string]$FilePath
    )

    if ($FilePath -and (Test-Path $FilePath)) {
        return Get-Content -Path $FilePath -Raw
    } elseif ($FilePath) {
        Write-Host "Warning: ASCII logo file not found at $FilePath" -ForegroundColor $PyKickColorWarning
    }

    return $PythonProjectASCIILogo
}

function Test-Yes {
    param (
        [string]$UserInput
    )

    return $UserInput -match "^(y|yes)$"
}

function Show-Help {
    $Options = @(
        @{Option = "-ProjectName <string>"; Description = "The name of your project - Default: $PythonProjectName"},
        @{Option = "-Description <string>"; Description = "The description of your project - Default: $PythonProjectDescription"},
        @{Option = "-Version <string>"; Description = "The version of your project - Default: $PythonProjectVersion"},
        @{
            Option = "-Year <string>"
            Description = "The license year for your project - Default: Current year ($PythonProjectLicenseYear)"
        }
        @{Option = "-Path <string>"; Description = "The path where your project will be created - Default: $PythonProjectPath"},
        @{Option = "-Author <string>"; Description = "The author of your project - Default: $PythonProjectAuthor"},
        @{Option = "-AuthorEmail <string>"; Description = "The author's email - Default: $PythonProjectAuthorEmail"},
        @{Option = "-AsciiLogoPath <string>"; Description = "The path to the ASCII logo file."},
        @{Option = "-Git"; Description = "Initialize a Git repository."},
        @{
            Option = "-GitInitialCommitMessage <string>";
            Description = "The initial commit message for the Git repository - Default: $PythonProjectGitInitialCommitMessage"
        },
        @{
            Option = "-GitDevBranchName <string>";
            Description = "The development branch name for the Git repository - Default: $PythonProjectGitDevBranchName"
        },
        @{Option = "-NoFollow"; Description = "Do not change the current location to your project path."},
        @{Option = "-Conda"; Description = "Create a new Conda environment."},
        @{
            Option = "-CondaPythonVersion <string>";
            Description = "The Python version for the Conda environment - Default: $PythonProjectCondaPythonVersion"
        },
        @{Option = "-CondaEnvName <string>"; Description = "The name of the Conda environment - Default: $PythonProjectCondaEnvName"},
        @{Option = "-Sphinx"; Description = "Generate Sphinx documentation structure."}
        @{Option = "-MakeDir"; Description = "Create the directory if it does not exist."},
        @{Option = "-Force"; Description = "Overwrite the data if the directory already exists."},
        @{Option = "-Silent"; Description = "Run the script in silent mode without displaying output."},
        @{Option = "-Y"; Description = "Automatically confirm the generation of your project."},
        @{
            Option = "-FullSetup";
            Description = "Initialize a Git repository, create a new Conda environment, and generate Sphinx documentation."
        },
        @{Option = "-Wizard"; Description = "Launch the setup wizard to configure your project."},
        @{
            Option = "-RevertOnError";
            Description = "Revert the changes if any error occurs (not applicable for existing project i.e. with -Force option)."
        },
        @{Option = "-Reset"; Description = "Reset the pykick configuration file to the default values."},
        @{Option = "-Edit"; Description = "Edit the PyKick configuration file in VS Code or Notepad."},
        @{Option = "-V"; Description = "Display the version of PyKick."},
        @{Option = "-Help"; Description = "Display this help message."}
    )

    Write-Host "Usage: " -ForegroundColor $PyKickColorDefaultText -NoNewline
    Write-Host "pykick " -ForegroundColor $PyKickColorWarning -NoNewline
    Write-Host "[Options]" -ForegroundColor $PyKickColorDefaultOption
    Write-Host ""
    Write-Host "Options:" -ForegroundColor $PyKickColorDefaultText

    foreach ($Option in $Options) {
        Write-Host (" {0,-37}" -f $Option.Option) -ForegroundColor $PyKickColorDefaultOption -NoNewline
        Write-Host $Option.Description -ForegroundColor $PyKickColorInfo
    }
    Write-Host ""
}

function Show-Info {
    param (
        [string]$Message,
        [string]$Value,
        [int]$Spacing = 47,
        [string]$Color = $PyKickColorInfo
    )

        Write-Host (" {0,$Spacing}" -f $Message) -ForegroundColor $Color -NoNewline
        Write-Host $Value -ForegroundColor $Color
}

function Get-FormattedAsciiLogo {
    param (
        [string]$AsciiLogo,
        [string]$Prefix = "##*",
        [int]$Spacing = 5
    )

    $LogoLines = $AsciiLogo -split "`n"
    $FormattedLines = @()
    $PrefixWithSpacing = "{0,-$($Prefix.Length + $Spacing)}" -f $Prefix

    foreach ($Line in $LogoLines) {
        $FormattedLines += "$PrefixWithSpacing $Line"
    }

    return $FormattedLines -join "`n"
}

function Save-CursorPosition {
    return @{
        Left = [System.Console]::CursorLeft
        Top = [System.Console]::CursorTop
    }
}

function Restore-CursorPosition {
    param (
        [hashtable]$Position
    )
    $Width = [System.Console]::WindowWidth

    [System.Console]::SetCursorPosition($Position.Left, $Position.Top)

    Write-Host (" " * $Width) -NoNewline
    [System.Console]::SetCursorPosition($Position.Left, $Position.Top)
}

function Open-ScriptInEditor {
    param (
        [string]$ScriptPath
    )

    if (Get-Command code -ErrorAction SilentlyContinue) {
        code $ScriptPath
    } elseif ($IsWindows) {
        notepad $ScriptPath
    } elseif ($IsMacOS) {
        open -a "TextEdit" $ScriptPath
    } elseif ($IsLinux) {
        if (Get-Command gedit -ErrorAction SilentlyContinue) {
            gedit $ScriptPath
        } elseif (Get-Command nano -ErrorAction SilentlyContinue) {
            nano $ScriptPath
        } else {
            Show-FormattedMessage -MessagesAndColors @(
                @{"No suitable editor found. Please install VSCode, Gedit, or Nano." = $PyKickColorInfo}
                @{"Or you can open directly the configuration file " = $PyKickColorInfo}
                @{$ScriptPath = $PyKickColorDefaultText}
                @{" in your favorite editor." = $PyKickColorInfo}
            )
        }
    } else {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Unsupported operating system." = $PyKickColorError}
        )
    }
}

function Get-NormalizedDescription {
    param (
        [string]$ProjectName,
        [string]$Description
    )

    if ($Description -eq $PythonProjectDescription -and $ProjectName -ne $PythonProjectName) {
        return "Description of $ProjectName 😁"
    }

    return $Description
}

function Invoke-PyKick {
    function Read-Input {
        param (
            [string]$Prompt,
            [string]$Default = ""
        )
        $savedPosition = Save-CursorPosition

        $input = Read-Host "$Prompt (Default: $Default)"
        if ($input -eq "") {
            $input = $Default
        }

        Restore-CursorPosition -Position $savedPosition

        return $input
    }

    $ProjectMeta = @{
        ProjectName = Read-Input -Prompt "Enter your project name" -Default $PythonProjectName
        Description = Read-Input -Prompt "Enter your project description" -Default $PythonProjectDescription
        Version = Read-Input -Prompt "Enter your project version" -Default $PythonProjectVersion
        Year = Read-Input -Prompt "Enter the license year" -Default $PythonProjectLicenseYear
        Path = Read-Input -Prompt "Enter your project path" -Default $PythonProjectPath
        Author = Read-Input -Prompt "Enter the author name" -Default $PythonProjectAuthor
        AuthorEmail = Read-Input -Prompt "Enter the author email" -Default $PythonProjectAuthorEmail
    }

    $ProjectMeta["AsciiLogoPath"] = Read-Input -Prompt "Enter the ASCII logo file path (optional)"

    $GitInput = Read-Input -Prompt "Initialize Git repository? ([y]es/[n]o)" -Default "no"
    $ProjectMeta["Git"] = Test-Yes -UserInput $GitInput

    if ($ProjectMeta["Git"]) {
        $ProjectMeta["GitInitialCommitMessage"] = Read-Input `
            -Prompt "Enter the initial commit message" `
            -Default $PythonProjectGitInitialCommitMessage
        $ProjectMeta["GitDevBranchName"] = Read-Input `
            -Prompt "Enter the development branch name" `
            -Default $PythonProjectGitDevBranchName
    }

    $CondaEnvInput = Read-Input -Prompt "Create a new Conda environment? ([y]es/[n]o)" -Default "no"
    $ProjectMeta["Conda"] = Test-Yes -UserInput $CondaEnvInput

    if ($ProjectMeta["Conda"]) {
        $ProjectMeta["CondaPythonVersion"] = Read-Input `
            -Prompt "Enter the Python version for the Conda environment" `
            -Default $PythonProjectCondaPythonVersion
        $ProjectMeta["CondaEnvName"] = Read-Input `
            -Prompt "Enter the Conda environment name" `
            -Default $($ProjectMeta["ProjectName"] + "_P" + $ProjectMeta["CondaPythonVersion"])
    }

    $SphinxInput = Read-Input -Prompt "Generate Sphinx documentation structure? ([y]es/[n]o)" -Default "no"
    $ProjectMeta["Sphinx"] = Test-Yes -UserInput $SphinxInput

    return $ProjectMeta
}

function PyKick {
    [CmdletBinding()]
    param (
        [string]$ProjectName = $PythonProjectName,
        [string]$Description = $PythonProjectDescription,
        [string]$Version = $PythonProjectVersion,
        [string]$Year = $PythonProjectLicenseYear,
        [string]$Path = $PythonProjectPath,
        [string]$Author = $PythonProjectAuthor,
        [string]$AuthorEmail = $PythonProjectAuthorEmail,
        [string]$AsciiLogoPath,
        [switch]$Git,
        [string]$GitInitialCommitMessage = $PythonProjectGitInitialCommitMessage,
        [string]$GitDevBranchName = $PythonProjectGitDevBranchName,
        [switch]$NoFollow,
        [switch]$Conda,
        [string]$CondaPythonVersion = $PythonProjectCondaPythonVersion,
        [string]$CondaEnvName = $PythonProjectCondaEnvName,
        [switch]$Sphinx,
        [switch]$MakeDir,
        [switch]$Force,
        [switch]$Silent,
        [switch]$Y,
        [switch]$FullSetup,
        [switch]$Wizard,
        [switch]$RevertOnError,
        [switch]$Reset,
        [switch]$Edit,
        [switch]$V,
        [switch]$Help
    )

    Show-Banner

    if ($V) {
        Show-FormattedMessage -MessagesAndColors @(
            @{"PyKick version: " = $PyKickColorInfo},
            @{$PyKickVersion = $PyKickColorDefaultText}
        )

        return
    }

    if ($Help) {
        Show-Help

        return
    }

    if ($Edit) {
        Open-ScriptInEditor -ScriptPath $PyKickConfigFilePath

        return
    }

    if ($Reset) {
        Initialize-PyKick -ConfigFilePath $PyKickConfigFilePath -DefaultConfig $PYKICK_CONF_PS1 -Reset:$true

        return
    }

    if ($Wizard) {
        $WizardInput = Invoke-PyKick
        $ProjectName = $WizardInput.ProjectName
        $Description = $WizardInput.Description
        $Version = $WizardInput.Version
        $Year = $WizardInput.Year
        $Path = $WizardInput.Path
        $Author = $WizardInput.Author
        $AuthorEmail = $WizardInput.AuthorEmail
        $AsciiLogoPath = $WizardInput.AsciiLogoPath
        $Git = $WizardInput.Git
        $GitInitialCommitMessage = $WizardInput.GitInitialCommitMessage
        $GitDevBranchName = $WizardInput.GitDevBranchName
        $Conda = $WizardInput.Conda
        $CondaPythonVersion = $WizardInput.CondaPythonVersion
        $CondaEnvName = $WizardInput.CondaEnvName
        $Sphinx = $WizardInput.Sphinx

        $MakeDir = $true
    }

    $Path = Join-Path -Path $Path -ChildPath $ProjectName

    if (-not (Test-Schema -Value $ProjectName -Schema 'PythonProjectName')) {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: The project name " = $PyKickColorError},
            @{$ProjectName = $PyKickColorDefaultText},
            @{" is invalid. It must be lowercase, without spaces," = $PyKickColorError}
            @{" and use only letters, numbers, and underscores." = $PyKickColorError}
        )

        return
    }

    if (-not (Test-Schema -Value $Year -Schema 'Year')) {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: The year " = $PyKickColorError},
            @{$Year = $PyKickColorDefaultText},
            @{" is invalid. It must be a four-digit number." = $PyKickColorError}
        )

        return
    }

    if (-not (Test-Schema -Value $AuthorEmail -Schema 'Email')) {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: The email " = $PyKickColorError},
            @{$AuthorEmail = $PyKickColorDefaultText},
            @{" is invalid." = $PyKickColorError}
        )

        return
    }

    if (-not $Force -and (Test-Path -Path $Path)) {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: The directory " = $PyKickColorError},
            @{$Path = $PyKickColorDefaultText},
            @{" already exists. You can use the option" = $PyKickColorError},
            @{" -Force" = $PyKickColorDefaultOption},
            @{" to overwrite the data." = $PyKickColorError}
        )

        return
    }

    try {
        $PyKickErrors = $false
        $PyKickRevertConda = $false

        $AsciiLogo = Import-Logo -FilePath $AsciiLogoPath
        if ($FullSetup) {
            $Git = $true
            $Conda = $true
            $Sphinx = $true
        }

        $ProjectSrcPath = Join-Path -Path $Path -ChildPath (Join-Path -Path $PyKickSrcFolder -ChildPath $ProjectName)
        $Description = Get-NormalizedDescription -ProjectName $ProjectName -Description $Description

        if ($Sphinx) {
            $ProjectDocsPath = Join-Path -Path $Path -ChildPath $PyKickDocsFolder
            $ProjectDocsBuildPath = Join-Path -Path $ProjectDocsPath -ChildPath $PyKickDocsBuildFolder
            $ProjectDocsSourcePath = Join-Path -Path $ProjectDocsPath -ChildPath $PyKickDocsSourceFolder
            $ProjectDocsSourceProjectPath = Join-Path -Path $ProjectDocsSourcePath -ChildPath $ProjectName
            $ProjectDocsSourceNotesPath = Join-Path -Path $ProjectDocsSourcePath -ChildPath $PyKickDocsSourceNotesFolder
            $ProjectDocsSourceStaticPath = Join-Path -Path $ProjectDocsSourcePath -ChildPath $PyKickDocsSourceStaticFolder
            $ProjectDocsSourceStaticCssPath = Join-Path -Path $ProjectDocsSourceStaticPath -ChildPath $PyKickDocsSourceStaticCssFolder
            $ProjectDocsSourceStaticJsPath = Join-Path -Path $ProjectDocsSourceStaticPath -ChildPath $PyKickDocsSourceStaticJsFolder
        }

        if (-not $Silent) {
            Write-Host "Synthesizing project ..." -ForegroundColor $PyKickColorInfo
            Write-Host ""
            Show-Info -Message "Project name : " -Value $ProjectName
            Show-Info -Message "Description : " -Value $Description
            Show-Info -Message "Version : " -Value $Version
            Show-Info -Message "Path : " -Value $Path
            Show-Info -Message "Author : " -Value $Author
            Show-Info -Message "Author email : " -Value $AuthorEmail
            Show-Info -Message "License year : " -Value $Year
            Show-Info -Message "ASCII logo path : " -Value ""
            Write-Host ""
            Write-Host $AsciiLogo -ForegroundColor $PyKickColorDefaultOption
            Write-Host ""
            Show-Info -Message "Generating Git repository : " -Value $Git
            if ($Git) {
                Show-Info -Message "Initial commit message : " -Value $GitInitialCommitMessage
                Show-Info -Message "Development branch name : " -Value $GitDevBranchName
            }
            Show-Info -Message "Creating Conda environment : " -Value $Conda
            if ($Conda) {
                Show-Info -Message "Conda python version : " -Value $CondaPythonVersion
                Show-Info -Message "Conda environment name : " -Value $CondaEnvName
            }
            Show-Info -Message "Generating Sphinx documentation structure : " -Value $Sphinx
            Write-Host ""
        }

        if (-not $Y) {
            $Confirm = $true
            $UserConfirm = Read-Host "Do you want to continue with your current settings? ([y]es/[n]o) (Default: yes)"

            if ($UserConfirm -ne "" -and -not (Test-Yes -UserInput $UserConfirm)) {
                $Confirm = $false
            }

            if (-not $Confirm) {
                Write-Host ""
                Write-Host "o( ^ ^ )o Bye bye, $env:USERNAME o( ^ ^ )o" -ForegroundColor $PyKickColorInfo
                Write-Host ""
                return
            }
        }

        if (-not (Test-BaseJsonFoldersStructure -JsonStructure $BaseJsonFoldersStructure)) {
            return
        }

        if ($MakeDir) {
            try {
                New-Item -ItemType Directory -Path $Path -Force | Out-Null
            } catch {
                Show-FormattedMessage -MessagesAndColors @(
                    @{"Error: Unable to create the directory " = $PyKickColorError},
                    @{$Path = $PyKickColorDefaultText},
                    @{". Please check your permissions." = $PyKickColorError}
                )

                return
            }
        }

        if ($Sphinx) {
            $CombinedJsonFoldersStructure = Update-Holders -Content $BaseJsonFoldersStructure `
                -Placeholders @{"{{ PYTHON_PROJECT_SPHINX_FOLDER_STRUCTURE }}" = $(
                    Update-Holders -Content $PyKickSphinxJsonFolderStructure `
                    -Placeholders @{"{{ PYTHON_PROJECT_NAME }}" = $ProjectName}
                )}
        } else {
            $CombinedJsonFoldersStructure = Update-Holders -Content $BaseJsonFoldersStructure `
                -Placeholders @{"{{ PYTHON_PROJECT_SPHINX_FOLDER_STRUCTURE }}" = ""}
        }

        if (-not (Test-JsonStructure -JsonStructure `
                    (Update-Holders -Content $CombinedJsonFoldersStructure `
                        -Placeholders @{"{{ PYTHON_PROJECT_NAME }}" = $ProjectName}))) {
            return
        }

        New-PyProjectFile -Path $Path -FileName $PythonProjectRequirementsFile -Content $PythonProjectRequirements
        New-PyProjectFile -Path $Path -FileName $PythonProjectLicenseFile -Placeholders @{
            "{{ PYTHON_PROJECT_AUTHOR }}" = $Author
            "{{ PYTHON_PROJECT_LICENSE_YEAR }}" = $Year;
        } -Content $PythonProjectLicense
        New-PyProjectFile -Path $Path -FileName $PythonProjectChangelogFile -Placeholders @{
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
        } -Content $PythonProjectChangelog
        New-PyProjectFile -Path $Path -FileName $PythonProjectReadmeFile -Placeholders @{
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
            "{{ PYTHON_PROJECT_AUTHOR }}" = $Author;
            "{{ PYTHON_PROJECT_LICENSE_YEAR }}" = $Year;
            "{{ PYTHON_PROJECT_VERSION }}" = $Version;
            "{{ PYTHON_PROJECT_LICENSE }}" = $(Update-Holders -Content $PythonProjectLicense -Placeholders @{
                "{{ PYTHON_PROJECT_AUTHOR }}" = $Author;
                "{{ PYTHON_PROJECT_LICENSE_YEAR }}" = $Year})
        } -Content $PythonProjectReadme
        New-PyProjectFile -Path $Path -FileName $PythonProjectTomlFile -Placeholders @{
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
            "{{ PYTHON_PROJECT_DESCRIPTION }}" = $Description;
            "{{ PYTHON_PROJECT_AUTHOR }}" = $Author;
            "{{ PYTHON_PROJECT_AUTHOR_EMAIL }}" = $AuthorEmail
        } -Content $PythonProjectToml

        New-NewFolderStructure -RootPath $Path -FolderStructureJson $CombinedJsonFoldersStructure -Placeholders @{
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
        } -Sphinx:$Sphinx

        if (-not (Test-Path -Path $ProjectSrcPath)) {
            Show-FormattedMessage -MessagesAndColors @(
                @{"Error: The source directory " = $PyKickColorError},
                @{$ProjectSrcPath = $PyKickColorDefaultText},
                @{" does not exist.`nPlease create the source directory manually" = $PyKickColorError},
                @{" or modify the JsonFoldersStructure to auto generate the" = $PyKickColorError}
                @{" src" = $PyKickColorDefaultText}
                @{" folder.`nThe current project structure defined in" = $PyKickColorError}
                @{' $BaseJsonFoldersStructure' = $PyKickColorDefaultText}
                @{" is : " = $PyKickColorError}
            )
            Write-Host ""
            Show-Tree -JsonStructure $CombinedJsonFoldersStructure
            Write-Host ""

            $PyKickErrors = $true
        }

        if ($Conda -and (Get-Command conda -ErrorAction SilentlyContinue)) {
            $RequirementsFilePath = Join-Path -Path $Path -ChildPath $PythonProjectRequirementsFile
            New-CondaEnv `
                -EnvName $CondaEnvName `
                -PythonVersion $CondaPythonVersion `
                -RequirementsFilePath $RequirementsFilePath `
                -Path $Path `
                -Silent:$Silent

            $PyKickRevertConda = $true
        } elseif ($Conda) {
            Show-FormattedMessage -MessagesAndColors @(
                @{"Error: " = $PyKickColorError},
                @{"Conda is not installed. Please install Conda to create the environment." = $PyKickColorError}
            )

            $PyKickErrors = $true
        }

        New-PyProjectFile -Path $ProjectSrcPath -FileName $PythonProjectInitFile -Placeholders @{
            "{{ PYTHON_PROJECT_ASCII_LOGO }}" = $AsciiLogo;
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
        } -Content $PythonProjectInit
        New-PyProjectFile -Path $ProjectSrcPath -FileName $PythonProjectMainFile -Placeholders @{
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
        } -Content $PythonProjectMain
        New-PyProjectFile -Path $ProjectSrcPath -FileName $PythonProjectMetaFile -Placeholders @{
            "{{ PYTHON_PROJECT_ASCII_LOGO }}" = $AsciiLogo;
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
            "{{ PYTHON_PROJECT_VERSION }}" = $Version;
            "{{ PYTHON_PROJECT_DESCRIPTION }}" = $Description;
            "{{ PYTHON_PROJECT_AUTHOR }}" = $Author;
            "{{ PYTHON_PROJECT_AUTHOR_EMAIL }}" = $AuthorEmail;
            "{{ PYTHON_PROJECT_LICENSE }}" = $(Update-Holders -Content $PythonProjectLicense -Placeholders @{
                "{{ PYTHON_PROJECT_AUTHOR }}" = $Author;
                "{{ PYTHON_PROJECT_LICENSE_YEAR }}" = $Year})
        } -Content $PythonProjectMeta
        $PythonProjectCliBlanckContent = ""
        if ($ProjectName -eq "chopper") { $PythonProjectCliBlanckContent = $PythonProjectCliChopper }  # chopper is a special case
        New-PyProjectFile -Path $ProjectSrcPath -FileName $PythonProjectCliFile -Placeholders @{
            "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
            "{{ PYTHON_PROJECT_CLI_CHOPPER }}" = $PythonProjectCliBlanckContent
        } -Content $PythonProjectCli

        if ($Sphinx) {
            $IsSphinxStructure = Test-SphinxTreeStructure -Paths @(
                $ProjectDocsPath, $ProjectDocsBuildPath, $ProjectDocsSourcePath, $ProjectDocsSourceProjectPath,
                $ProjectDocsSourceNotesPath, $ProjectDocsSourceStaticPath, $ProjectDocsSourceStaticCssPath,
                $ProjectDocsSourceStaticJsPath
            ) -CombinedJsonFoldersStructure $CombinedJsonFoldersStructure -Placeholders @{
                "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
            }

            if (-not $IsSphinxStructure) {
                $PyKickErrors = $true
            }

            New-PyProjectFile -Path $ProjectDocsPath -FileName $PythonProjectSphinxMakefileFile -Content $PythonProjectSphinxMakefile
            New-PyProjectFile -Path $ProjectDocsPath -FileName $PythonProjectSphinxMakeBatFile -Content $PythonProjectSphinxMakeBat

            New-PyProjectFile -Path $ProjectDocsSourcePath -FileName $PythonProjectSphinxConfPyFile -Placeholders @{
                "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
                "{{ PYTHON_PROJECT_AUTHOR }}" = $Author;
                "{{ PYTHON_PROJECT_VERSION }}" = $Version;
                "{{ PYTHON_PROJECT_LICENSE_YEAR }}" = $Year;
                "{{ PYKICK_NAME }}" = $PyKickName;
            } -Content $PythonProjectSphinxConfPy
            New-PyKickPng -Path $ProjectDocsSourcePath
            New-PyProjectFile -Path $ProjectDocsSourcePath -FileName $PythonProjectSphinxBrRstFile `
                -Content $PythonProjectSphinxBrRst
            New-PyProjectFile -Path $ProjectDocsSourcePath -FileName $PythonProjectSphinxIndexRstFile `
                -Placeholders @{
                    "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
                    "{{ PYKICK_GENERATION_DATE }}" = $(Get-Date -Format "dddd MMM dd HH:mm:ss yyyy");
                    "{{ UNDERLINES_CHAR }}" = '=' * ("$ProjectName Documentation".Length)
                } -Content $PythonProjectSphinxIndexRst
            New-PyProjectFile -Path $ProjectDocsSourcePath -FileName $PythonProjectSphinxReflinksRstFile `
                -Content $PythonProjectSphinxReflinksRst

            New-PyProjectFile -Path $ProjectDocsSourceProjectPath -FileName $PythonProjectSphinxProjectIndexRstFile `
                -Placeholders @{
                    "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
                } -Content $PythonProjectSphinxProjectIndexRst
            New-PyProjectFile -Path $ProjectDocsSourceProjectPath `
                -FileName "$ProjectName$PythonProjectSphinxProjectModulesRstFile" `
                -Placeholders @{
                    "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
                    "{{ UNDERLINES_CHAR }}" = '=' * $("$ProjectName.cli".Length)
                } -Content $PythonProjectSphinxProjectModulesRst

            New-PyProjectFile -Path $ProjectDocsSourceNotesPath -FileName $PythonProjectSphinxNotesBadgesRstFile `
                -Placeholders @{
                    "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
                } -Content $PythonProjectSphinxNotesBadgesRst
            New-PyProjectFile -Path $ProjectDocsSourceNotesPath -FileName $PythonProjectSphinxNotesLogoRstFile `
                -Placeholders @{
                    "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
                } -Content $PythonProjectSphinxNotesLogoRst
            New-PyProjectFile -Path $ProjectDocsSourceNotesPath -FileName $PythonProjectSphinxNotesWelcomeRstFile `
                -Placeholders @{
                    "{{ PYTHON_PROJECT_NAME }}" = $ProjectName
                } -Content $PythonProjectSphinxNotesWelcomeRst
            New-PyProjectFile -Path $ProjectDocsSourceNotesPath -FileName $PythonProjectSphinxNotesInstallRstFile `
                -Placeholders @{
                    "{{ PYTHON_PROJECT_NAME }}" = $ProjectName;
                    "{{ PYTHON_PROJECT_VERSION }}" = $Version
                } -Content $PythonProjectSphinxNotesInstallRst

            New-PyProjectFile -Path $ProjectDocsSourceStaticCssPath `
                -FileName "$ProjectName$PythonProjectSphinxStaticCssFile" `
                -Content $PythonProjectSphinxStaticCss
            New-PyProjectFile -Path $ProjectDocsSourceStaticJsPath `
                -FileName "$ProjectName$PythonProjectSphinxStaticJsFile" `
                -Content $PythonProjectSphinxStaticJs
        }

        if ($Git -and (Get-Command git -ErrorAction SilentlyContinue)) {
            New-PyProjectFile -Path $Path -FileName $PythonProjectGitIgnoreFile -Content $PythonProjectGitIgnore
            Initialize-GitRepo -Path $Path -InitialCommit $GitInitialCommitMessage -BranchName $GitDevBranchName -Silent:$Silent
        } elseif ($Git) {
            Show-FormattedMessage -MessagesAndColors @(
                @{"Error: " = $PyKickColorError},
                @{"Git is not installed. Please install Git to initialize the repository." = $PyKickColorError}
            )

            $PyKickErrors = $true
        }

        if (-not $PyKickErrors) {
            Write-Host ""
            Show-FormattedMessage -MessagesAndColors @(
                @{"The generation of your project " = $PyKickColorSuccess},
                @{$ProjectName = $PyKickColorDefaultText},
                @{" has been successfully completed at " = $PyKickColorSuccess},
                @{$Path = $PyKickColorDefaultText}
            )

            if (-not $NoFollow) {
                Set-Location -Path $Path
            }
        }
    } catch [System.UnauthorizedAccessException] {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: Access denied at " = $PyKickColorError},
            @{$Path = $PyKickColorDefaultText},
            @{". Please check your permissions." = $PyKickColorError}
        )
        $PyKickErrors = $true
    } catch [System.IO.DirectoryNotFoundException] {
        Show-FormattedMessage -MessagesAndColors @(
            @{"Error: The directory " = $PyKickColorError},
            @{$Path = $PyKickColorDefaultText},
            @{" does not exist. You can use the option" = $PyKickColorError},
            @{" -MakeDir" = $PyKickColorDefaultOption},
            @{" to create it." = $PyKickColorError}
        )
        $PyKickErrors = $true
    } catch {
        Show-FormattedMessage -MessagesAndColors @(
            @{"There was a problem during the generation at " = $PyKickColorError},
            @{$Path = $PyKickColorDefaultText}
        )
        $PyKickErrors = $true

        Write-Host $_.Exception.Message -ForegroundColor $PyKickColorError
    } finally {
        if ($PyKickErrors -and $MakeDir) {
            if (-not $RevertOnError) {
                $RM = "Some errors occur during the generating process of $ProjectName, revert changes? ([y]es/[n]o) (Default: no)"
                Write-Host ""
                $RevertOnErrorInput = Read-Host -Prompt $RM
                $RevertOnError = Test-Yes -UserInput $RevertOnErrorInput
            }
            if ($RevertOnError) {
                Restore-Changes -Path $(Resolve-Path -Path $Path)
                if ($PyKickRevertConda) {
                    Restore-Conda -EnvName $CondaEnvName
                }
            }
        }
    }
}
#+#/ PYKICK #########################################################################################