import json
import os
import pickle
from pathlib import Path
from typing import Any

import aiofiles
import orjson
import tomllib

from . import bcolor, bfile, bfunc, bpath
from .btype import Null, XPath


async def write_text(file: XPath, content: str, encoding: str = 'utf8', newline: str = '\n'):
    file = bpath.get(file)
    bpath.make(file.parent)
    async with aiofiles.open(file, 'w', encoding=encoding, newline=newline) as f:
        return await f.write(content)


async def write_bytes(file: XPath, data: bytes):
    file = bpath.get(file)
    bpath.make(file.parent)
    async with aiofiles.open(file, 'wb') as f:
        return await f.write(data)


async def write_json(file: XPath, data: Any, mini: bool = True):
    if mini:
        content = bfunc.json_dumps_mini(data)
    else:
        content = json.dumps(data, ensure_ascii=False, sort_keys=True, indent=4)
    await write_text(file, content)


async def write_pickle(file: XPath, data: Any):
    await write_bytes(file, pickle.dumps(data))


async def read_text(file: XPath, encoding: str = 'utf8'):
    data = await read_bytes(file)
    # 针对 UTF8 判断移除 BOM 头
    if encoding == 'utf8':
        if data.startswith(b'\xef\xbb\xbf'):
            data = data[3:]
    return data.decode(encoding)


async def read_bytes(file: XPath):
    async with aiofiles.open(file, 'rb') as f:
        return await f.read()


async def read_json(file: XPath):
    return orjson.loads(await read_bytes(file))


async def read_pickle(file: XPath):
    return pickle.loads(await read_bytes(file))


async def read_toml(file: XPath):
    return tomllib.loads(await read_text(file))


async def md5(file: XPath):
    return bfunc.md5_bytes(await read_bytes(file))


async def crc(file: XPath):
    return bfunc.crc_bytes(await read_bytes(file))


async def make_files(content: str, output: Path = Null, key: str = '>>>'):
    if output is Null:
        output = Path(os.curdir).absolute()
    ary = content.split(key)
    ary = [x.strip() for x in ary]
    ary = [x for x in ary if x]
    ary.sort()
    for substr in ary:
        sub_ary = substr.replace('\r\n', '\n').split('\n')
        file_name = sub_ary.pop(0)
        file = output / file_name
        bcolor.print_yellow(file)
        await bfile.write_text(
            file,
            '\n'.join(sub_ary).strip(),
        )


async def to_lf(file: XPath):
    content = await read_text(file)
    await write_text(file, content.replace('\r\n', '\n'))
