using System;
using System.IO;
using UnityEngine;

public class SaveSystem
{
    private static SaveData _saveData = new SaveData();

    [System.Serializable]
    public struct SaveData
    {
        public QuestSaveData QuestData;
        public StoryboolSaveData StoryboolData;
        public InventorySaveData InventorySaveData;
        public TimeSaveData TimeSaveData;
        public PlayerSaveData PlayerSaveData;
        public SoundSettingSaveData SoundSettingSaveData;
    }

    public static string SaveFileName()
    {
        return Application.persistentDataPath + "/save.data";
    }

    public static void GenerateCorruptedSaveReadme()
    {
        string path = Application.persistentDataPath + "/README.txt";
        string errorText = "Your save was corrupted.\n\n" +
            "This can happen when you edit the save manually, or if the game closed while saving. Your\n" +
            "corrupted save file has been saved in this directory as 'save.data.backup' if you'd like to\n" +
            "try manually fixing it. It should follow standard JSON formatting.\n\n" +
            "Once you fix it, just delete the current save.data file, and remove the '.backup' from your \n" +
            "old save file. Good luck, and sorry for the inconvenience!";

        File.WriteAllText(path, errorText);
    }

    public static void Save()
    {
        HandleSaveData();

        File.WriteAllText(SaveFileName(), JsonUtility.ToJson(_saveData, true));
    }

    public static void ClearSave()
    {
        try
        {
            File.Delete(SaveFileName());
            Debug.Log("File deleted successfully. Stop and restart player.");
        }
        catch (FileNotFoundException)
        {
            // file doesn't exist, don't need to do anything
        }
    }

    private static void HandleSaveData()
    {
        GameManager.Instance.SaveStoryBools(ref _saveData.StoryboolData);
        GameManager.Instance.Inventory.SaveInventory(ref _saveData.InventorySaveData);
        GameManager.Instance.TimeManager.SaveTime(ref _saveData.TimeSaveData);
        GameManager.Instance.PlayerManager.SavePlayerData(ref _saveData.PlayerSaveData);
        QuestRegistry.Instance.SaveQuestData(ref _saveData.QuestData);
        GameManager.Instance.SoundSettingManager.SaveSoundSettingsData(ref _saveData.SoundSettingSaveData);
    }

    public static void Load()
    {
        string saveContent;
        
        try
        {
            saveContent = File.ReadAllText(SaveFileName());
        }
        catch (FileNotFoundException)
        {
            Save(); // create new save file if one does not exist
            saveContent = File.ReadAllText(SaveFileName());
        }

        try
        {
            _saveData = JsonUtility.FromJson<SaveData>(saveContent);
        }
        catch (ArgumentException)
        {
            // Likely a JSON parse error. Let's back up the old version of the save and
            // make a new one for now

            File.WriteAllText(SaveFileName() + ".backup", saveContent);
            GenerateCorruptedSaveReadme();
            Save();
        }

        HandleLoadData();
    }

    public static void HandleLoadData()
    {
        GameManager.Instance.LoadStoryBools(_saveData.StoryboolData);
        GameManager.Instance.Inventory.LoadInventory(_saveData.InventorySaveData);
        GameManager.Instance.TimeManager.LoadTime(_saveData.TimeSaveData);
        GameManager.Instance.PlayerManager.LoadPlayerData(_saveData.PlayerSaveData);
        QuestRegistry.Instance.LoadQuestData(_saveData.QuestData);
        GameManager.Instance.SoundSettingManager.LoadSoundSettingsData(_saveData.SoundSettingSaveData);
    }
}
