import struct
import json
from typing import List, Dict, Any

class CharacterStats:
    stats_info = []

    def __init__(self, u: bytes):
        elements = ['Fire', 'Water', 'Wind', 'Earth', 'Dark']
        stats = ['Str', 'Vit', 'Tec', 'Agi', 'Luck']
        def_skills = ['Void', 'Absorb', 'Reflect', 'Weak', 'Norm']

        self.id = u[0] + u[1] * 256   # uint16
        self.Lvl = u[2]         # byte
        self.Str = u[3]         # byte
        self.Vit = u[4]         # byte
        self.Tec = u[5]         # byte
        self.Agi = u[6]         # byte
        self.Luc = u[7]         # byte
        elId = (u[8] >> 4) & 0x0F
        self.Element = {'id' : elId, 'value': elements[elId]}
        bId = u[8] & 0x0F
        self.LvlBonus = {'id': bId, 'value' : stats[bId] + "+1"}
        self.Stat_info = {'id': u[9], 'info': stats_info[u[9]] }# byte
        self.Spell_id_1 = u[10]  # byte
        self.Spell_id_2 = u[11] # byte
        self.Spell_id_3 = u[12] # byte
        self.Spell_id_4 = u[13] # byte
        self.Spell_id_5 = u[14] # byte
        self.Spell_id_6 = u[15] # byte
        
        stats_bytes = u[16:24]  # 4 байта = 32 бита = 16 полей по 4 бита
        self.stats = {
        "unk1": (u[16] >> 4) & 0x0F,
        "unk2": u[16] & 0x0F,
        "unk3": (u[17] >> 4) & 0x0F,
        "dark": {'id': u[17] & 0x0F, 'value' : def_skills[u[17] & 0x0F]},
        "unk5": (u[18] >> 4) & 0x0F,
        "unk6": u[18] & 0x0F,
        "unk7": (u[19] >> 4) & 0x0F,
        "unk8": u[19] & 0x0F,
        "unk9": (u[20] >> 4) & 0x0F,
        "unk10": u[20] & 0x0F,
        "unk11": (u[21] >> 4) & 0x0F,
        "unk12": u[21] & 0x0F,
        # "water": {'id': (u[22] >> 4) & 0x0F, 'value': def_skills[(u[22] >> 4) & 0x0F]},
        "water???": (u[22] >> 4) & 0x0F,
        "unk14": u[22] & 0x0F,
        "unk15": (u[23] >> 4) & 0x0F,
        "unk16": u[23] & 0x0F
        }
        
        self.some_var = struct.unpack('<H', u[24:26])[0]  # uint16
    
    def to_dict(self) -> Dict[str, Any]:
        return {
            'id': self.id,
            'Lvl': self.Lvl,
            'Str': self.Str,
            'Vit': self.Vit,
            'Tec': self.Tec,
            'Agi': self.Agi,
            'Luc': self.Luc,
            'Element': self.Element,
            'LvlBonus': self.LvlBonus,
            'Stat_info': self.Stat_info,
            'Spell_id_1': self.Spell_id_1,
            'Spell_id_2': self.Spell_id_2,
            'Spell_id_3': self.Spell_id_3,
            'Spell_id_4': self.Spell_id_4,
            'Spell_id_5': self.Spell_id_5,
            'Spell_id_6': self.Spell_id_6,
            'Stats': self.stats,
            'some_var': self.some_var,
        }
    

def read_binary_file(filename: str, start_offset: int, bytes_to_read: int) -> List[CharacterStats]:
    
    objects = []
    
    with open(filename, 'rb') as file:
        file.seek(start_offset)
        
        data = file.read(bytes_to_read)
        
        num_objects = len(data) // 26
        
        
        for i in range(num_objects):
            start_index = i * 26
            end_index = start_index + 26
            object_data = data[start_index:end_index]            
            obj = CharacterStats(object_data)
            objects.append(obj)
    
    return objects

def save_to_json(objects: List[CharacterStats], output_filename: str):
    data_to_save = [obj.to_dict() for obj in objects]
    
    with open(output_filename, 'w', encoding='utf-8') as json_file:
        json.dump(data_to_save, json_file, indent=2, ensure_ascii=False)
    
    print(f"Данные сохранены в {output_filename}, объектов: {len(objects)}")

def main():
    filename = "SLPS_021.00"
    start_offset = 341474            # Начальное смещение в байтах
    bytes_to_read = 3874         # Количество байтов для чтения (кратно 26)
    output_filename = "p_init_stats.json"

    global stats_info
    with open('Persona_stats.json', 'r', encoding='utf-8-sig') as f:
        stats_info = json.load(f)
    
    objects = read_binary_file(filename, start_offset, bytes_to_read)
    
    save_to_json(objects, output_filename)
    print(f"Saved to {output_filename}")        
       

if __name__ == "__main__":
    main()