#!/usr/bin/env python3
"""
Narzędzie do tworzenia plików .mar
"""

import struct
import sys


class MultiArrayWriter:
    def __init__(self, dimensions):
        """
        dimensions: list of ints, np. [3, 4, 2] dla tablicy [3][4][2]
        """
        self.dimensions = dimensions
        self.total_elements = 1
        for dim in dimensions:
            self.total_elements *= dim
        self.data = {}  # sparse: flat_index -> (type, value)
    
    def write_int(self, f, value):
        f.write(struct.pack('<i', value))
    
    def write_double(self, f, value):
        f.write(struct.pack('<i', int(value * 10000)))
    
    def write_bool(self, f, value):
        f.write(struct.pack('<?', value))
    
    def write_string(self, f, value):
        data = value.encode('utf-8')
        self.write_int(f, len(data))
        f.write(data)
    
    def write_variable(self, f, var_type, value):
        """type: 1=int, 2=string, 3=bool, 4=double"""
        self.write_int(f, var_type)
        
        if var_type == 1:
            self.write_int(f, value)
        elif var_type == 2:
            self.write_string(f, value)
        elif var_type == 3:
            self.write_bool(f, value)
        elif var_type == 4:
            self.write_double(f, value)
    
    def indices_to_flat(self, indices):
        """Konwertuje [x][y][z] na flat index"""
        flat = 0
        multiplier = 1
        
        for i in range(len(self.dimensions) - 1, -1, -1):
            flat += indices[i] * multiplier
            multiplier *= self.dimensions[i]
        
        return flat
    
    def set(self, indices, var_type, value):
        """
        Ustawia wartość pod wielowymiarowymi indeksami
        
        indices: list of ints, np. [1, 2, 0]
        var_type: 1=int, 2=string, 3=bool, 4=double
        value: wartość
        """
        if len(indices) != len(self.dimensions):
            raise ValueError(f"Wrong number of indices: got {len(indices)}, expected {len(self.dimensions)}")
        
        for i, idx in enumerate(indices):
            if idx < 0 or idx >= self.dimensions[i]:
                raise ValueError(f"Index {i} out of bounds: {idx} (max: {self.dimensions[i]-1})")
        
        flat_index = self.indices_to_flat(indices)
        self.data[flat_index] = (var_type, value)
    
    def set_int(self, indices, value):
        self.set(indices, 1, value)
    
    def set_string(self, indices, value):
        self.set(indices, 2, value)
    
    def set_bool(self, indices, value):
        self.set(indices, 3, value)
    
    def set_double(self, indices, value):
        self.set(indices, 4, value)
    
    def save(self, filepath):
        """Zapisuje do pliku .mar"""
        with open(filepath, 'wb') as f:
            # Liczba wymiarów
            self.write_int(f, len(self.dimensions))
            
            # Rozmiary wymiarów
            for dim in self.dimensions:
                self.write_int(f, dim)
            
            # Zapisz elementy (posortowane po indeksie)
            for flat_index in sorted(self.data.keys()):
                var_type, value = self.data[flat_index]
                self.write_int(f, flat_index)
                self.write_variable(f, var_type, value)
        
        print(f"Saved to {filepath}")
        print(f"  Dimensions: {self.dimensions}")
        print(f"  Total slots: {self.total_elements}")
        print(f"  Filled slots: {len(self.data)}")
        print(f"  Fill rate: {100*len(self.data)/self.total_elements:.1f}%")


def example_usage():
    """Przykład użycia"""
    # Stwórz tablicę 2D [5][3]
    mar = MultiArrayWriter([5, 3])
    
    # Wypełnij danymi
    mar.set_string([0, 0], "Reksio")
    mar.set_int([0, 1], 123)
    mar.set_double([1, 2], 3.14159)
    mar.set_bool([2, 0], True)
    mar.set_string([4, 2], "Koniec!")
    
    # Zapisz
    mar.save('/tmp/example.mar')


if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] == '--example':
        example_usage()
    else:
        print("MultiArray Writer - narzędzie do tworzenia plików .mar")
        print()
        print("Użycie w kodzie:")
        print()
        print("  from mar_writer import MultiArrayWriter")
        print()
        print("  # Stwórz tablicę [3][4][2]")
        print("  mar = MultiArrayWriter([3, 4, 2])")
        print()
        print("  # Ustaw wartości")
        print("  mar.set_string([0, 0, 0], 'Hello')")
        print("  mar.set_int([1, 2, 1], 42)")
        print("  mar.set_double([2, 3, 0], 3.14)")
        print("  mar.set_bool([0, 1, 1], True)")
        print()
        print("  # Zapisz")
        print("  mar.save('output.mar')")
        print()
        print("Uruchom z --example aby stworzyć przykładowy plik")
