import os
from datetime import datetime
import glob
from typing import Union

from resistics.common.io import checkAndMakeDir
from resistics.config.data import ConfigData
from resistics.config.io import loadConfig
from resistics.project.data import ProjectData
from resistics.project.utils import (
    projectText,
    projectBlock,
    projectWarning,
    projectError,
)


def newProject(
    projectPath: str,
    refTime: Union[str, datetime],
    configFile: str = "",
    name: str = "mtProj",
) -> ProjectData:
    """Create a new project in project path

    A new project will be created in project path. If the project path directory does not exist, a new one will be made. If a project already exists in project path, this project will be loaded and returned.

    Parameters
    ----------
    projectPath : str
        Path for the project directory
    refTime : datetime
        The reference time for the project
    configFile : str, optional
        Path to a configuration file
    name : str, optional (default is "mtProj")
        The name of the project file

    Returns
    -------
    ProjectData
        A project data object
    """
    # create project path directory
    checkAndMakeDir(projectPath)
    # reference time
    if isinstance(refTime, str):
        refTime = datetime.strptime(refTime, "%Y-%m-%d %H:%M:%S")
    # print info
    textLst = [
        "Creating a new project in path: {}".format(projectPath),
        "Project name: {}".format(name),
    ]
    projectBlock(textLst)

    # create the subdirectories
    projectFile = os.path.join(projectPath, "{}.prj".format(name))
    timePath = os.path.join(projectPath, "timeData")
    specPath = os.path.join(projectPath, "specData")
    statPath = os.path.join(projectPath, "statData")
    maskPath = os.path.join(projectPath, "maskData")
    transFuncPath = os.path.join(projectPath, "transFuncData")
    calPath = os.path.join(projectPath, "calData")
    imagePath = os.path.join(projectPath, "images")
    saveProjectFile(
        projectFile,
        refTime,
        calPath,
        timePath,
        specPath,
        statPath,
        maskPath,
        transFuncPath,
        imagePath,
    )

    # configuration file
    config = ConfigData(configFile)
    proj = ProjectData(
        projectFile,
        refTime,
        calPath,
        timePath,
        specPath,
        statPath,
        maskPath,
        transFuncPath,
        imagePath,
        config=config,
    )
    proj.printInfo()
    proj.config.printInfo()

    return proj


def loadProject(projectPath: str, configFile: str = "") -> ProjectData:
    """Load an existing project

    Parameters
    ----------
    projectPath : str
        Path for the project directory
    configFile : str
        Path to a configuration file

    Returns
    -------
    ProjectData
        A project data object
    """
    # search for the .prj file (hopefully only one)
    gl = glob.glob(os.path.join(projectPath, "*.prj"))
    if len(gl) == 0:
        projectError("Unable to find project file in path: {}".format(projectPath))
    projectFile: str = os.path.basename(gl[0])
    projectText(
        "Loading project file: {}".format(os.path.join(projectPath, projectFile))
    )
    projectPaths = loadProjectFile(os.path.join(projectPath, projectFile))

    # check the configuration file
    config = ConfigData(configFile)
    proj = ProjectData(
        projectFile,
        projectPaths["refTime"],
        projectPaths["calPath"],
        projectPaths["timePath"],
        projectPaths["specPath"],
        projectPaths["statPath"],
        projectPaths["maskPath"],
        projectPaths["transFuncPath"],
        projectPaths["imagePath"],
        config=config,
    )
    proj.printInfo()
    proj.config.printInfo()
    return proj


def saveProjectFile(
    filepath: str,
    refTime: datetime,
    calPath: str,
    timePath: str,
    specPath: str,
    statPath: str,
    maskPath: str,
    transFuncPath: str,
    imagePath: str,
) -> None:
    """Save the project file to filepath

    Parameters
    ----------
    filepath : str
        Path to project file
    """
    f = open(filepath, "w")
    f.write("Calibration data path = {}\n".format(calPath))
    f.write("Time data path = {}\n".format(timePath))
    f.write("Spectra data path = {}\n".format(specPath))
    f.write("Statistics data path = {}\n".format(statPath))
    f.write("Mask data path = {}\n".format(maskPath))
    f.write("TransFunc data path = {}\n".format(transFuncPath))
    f.write("Image data path = {}\n".format(imagePath))
    f.write("Reference time = {}\n".format(refTime.strftime("%Y-%m-%d %H:%M:%S")))
    f.close()


def loadProjectFile(filepath: str) -> None:
    """Load project from path to project file

    Parameters
    ----------
    filepath : str
        Path to project file

    Returns
    -------
    projPath : Dict[str, Union[str, datetime]]
        A dictionary with various project paths
    """
    f = open(filepath, "r")
    lines = f.readlines()
    f.close()
    projPaths = {}
    for l in lines:
        split = l.strip().split("=")
        if "Calibration data path" in l:
            projPaths["calPath"] = split[1].strip()
        if "Time data path" in l:
            projPaths["timePath"] = split[1].strip()
        if "Spectra data path" in l:
            projPaths["specPath"] = split[1].strip()
        if "Statistics data path" in l:
            projPaths["statPath"] = split[1].strip()
        if "Mask data path" in l:
            projPaths["maskPath"] = split[1].strip()
        if "TransFunc data path" in l:
            projPaths["transFuncPath"] = split[1].strip()
        if "Image data path" in l:
            projPaths["imagePath"] = split[1].strip()
        if "Reference time" in l:
            projPaths["refTime"] = datetime.strptime(
                split[1].strip(), "%Y-%m-%d %H:%M:%S"
            )
    return projPaths

