import csv
import numpy as np
import sys
import itertools
import math

def round_to_nearest_multiple(number, multiple):
    return int(round((number-0.001) / multiple) * multiple)

def process_csv(file_path, rounding_multiple):

    with open(file_path, 'r') as csv_file:
        # Read all lines from the file
        lines = list(csv_file)
        
        # Extract the first two rows
        row1, row2 = lines[0], lines[1]
        
        # Use csv.DictReader on the remaining lines
        reader = csv.DictReader(lines[2:])
        data = [row for row in reader]

    # Extract the "Value" column as a list of floats
    values = [float(row['Value']) for row in data]

    # Find min, max, and calculate the threshold
    min_value = min(values)
    max_value = max(values)
    threshold = (min_value + max_value) / 2

    # Compare values to the threshold and generate the "Bit" column
    bits = [1 if value > threshold else 0 for value in values]

    # Ignore leading zeros and start decoding from the first '1'
    first_one_index = next((i for i, bit in enumerate(bits) if bit == 1), None)
    if first_one_index is None:
        print("No '1' found in the data. Cannot start decoding.")
        return

    bits = bits[first_one_index:]

    # Find transitions, count 0s or 1s between transitions, and store bits with counts
    bit_count_pairs = []
    count = 1
    for i in range(1, len(bits)):
        if bits[i] != bits[i - 1]:  # Transition detected
            bit_count_pairs.append((bits[i - 1], count))
            count = 1  # Reset count
        else:
            count += 1
    bit_count_pairs.append((bits[-1], count))  # Append the final bit and its count

    # Round counts to the nearest multiple of the rounding_multiple
    rounded_counts = [round_to_nearest_multiple(count, rounding_multiple) for _, count in bit_count_pairs]

    # Generate the bit sequence "DecodedBits"
    decoded_bits = []
    for (bit, _), rounded_count in zip(bit_count_pairs, rounded_counts):
        num_bits = rounded_count // rounding_multiple
        if num_bits>4:
            num_bits=4
        decoded_bits.extend([bit] * num_bits)

    # BinaryMessage constants
    binary_message = [
        0b1101100010100111101101110111000100010111010111000100101010001100, #1
        0b1000100010011110010101110111010101001100110100010110101010011100,
        0b0110101011011010101011010010010011010101011101010111010010101010,
        0b1111000011110000111100001111000011110000111100001111000011110000,
        0b1010101010101010101010101010101010101010101010101010101010101010,
        0b0101010101010101010101010101010101010101010101010101010101010101,
        0b1110001110001110001110001110001110001110001110001110001110001110,
        0b0001110001110001110001110001110001110001110001110001110001110001,
        0b1010010110100101101001011010010110100101101001011010010110100101,
        0b0101101001011010010110100101101001011010010110100101101001011010,
        0b1101100010100111101101110111000100010111010111000100101010001100, #2
        0b1000100010011110010101110111010101001100110100010110101010011100,
        0b0110101011011010101011010010010011010101011101010111010010101010,
        0b1111000011110000111100001111000011110000111100001111000011110000,
        0b1010101010101010101010101010101010101010101010101010101010101010,
        0b0101010101010101010101010101010101010101010101010101010101010101,
        0b1110001110001110001110001110001110001110001110001110001110001110,
        0b0001110001110001110001110001110001110001110001110001110001110001,
        0b1010010110100101101001011010010110100101101001011010010110100101,
        0b0101101001011010010110100101101001011010010110100101101001011010,
        0b1101100010100111101101110111000100010111010111000100101010001100,
        0b1000100010011110010101110111010101001100110100010110101010011100,
        0b0110101011011010101011010010010011010101011101010111010010101010,
        0b1111000011110000111100001111000011110000111100001111000011110000,
        0b1010101010101010101010101010101010101010101010101010101010101010,
        0b0101010101010101010101010101010101010101010101010101010101010101,
        0b1110001110001110001110001110001110001110001110001110001110001110,
        0b0001110001110001110001110001110001110001110001110001110001110001,
        0b1010010110100101101001011010010110100101101001011010010110100101,
        0b0101101001011010010110100101101001011010010110100101101001011010,
        0b1101100010100111101101110111000100010111010111000100101010001100,
        0b1000100010011110010101110111010101001100110100010110101010011100,
        0b0110101011011010101011010010010011010101011101010111010010101010,
        0b1111000011110000111100001111000011110000111100001111000011110000,
        0b1010101010101010101010101010101010101010101010101010101010101010,
        0b0101010101010101010101010101010101010101010101010101010101010101,
        0b1110001110001110001110001110001110001110001110001110001110001110,
        0b0001110001110001110001110001110001110001110001110001110001110001,
        0b1010010110100101101001011010010110100101101001011010010110100101,
        0b0101101001011010010110100101101001011010010110100101101001011010,
        0b1101100010100111101101110111000100010111010111000100101010001100,
        0b1000100010011110010101110111010101001100110100010110101010011100,
        0b0110101011011010101011010010010011010101011101010111010010101010,
        0b1111000011110000111100001111000011110000111100001111000011110000,
        0b1010101010101010101010101010101010101010101010101010101010101010,
        0b0101010101010101010101010101010101010101010101010101010101010101,
        0b1110001110001110001110001110001110001110001110001110001110001110,
        0b0001110001110001110001110001110001110001110001110001110001110001,
        0b1010010110100101101001011010010110100101101001011010010110100101,
        0b0101101001011010010110100101101001011010010110100101101001011010
    ]

    # Print the file name and rounding multiple
    print(row1.strip())
    print(row2.strip())
    print(f"File Name: {file_path}")
    print(f"Photodiode Samples per Cycle: {rounding_multiple}")
    print(f"Minimum : {min_value}")
    print(f"Maximum : {max_value}")
    print(f"Threshold : {threshold}\n")
    
    # Compare DecodedBits to the binaryMessage constants and print results
    for i, constant in enumerate(binary_message):
        constant_bits = [(constant >> bit) & 1 for bit in range(63, -1, -1)]  # Convert to bit array
        decoded_segment = decoded_bits[i * 64 + math.floor(i/10):(i + 1) * 64 + math.floor(i/10)]
        match = decoded_segment == constant_bits  # Compare segment to constant
        print(f"Original 64-bit Sequence {i + 1}: {''.join(map(str, constant_bits))}")
        print(f"Decoded  64-bit Sequence {i + 1}: {''.join(map(str, decoded_segment))}")
        print(f"Match: {match}\n")

if __name__ == "__main__":
    if len(sys.argv) < 3:
        print("Usage: python script.py <csv_file> <rounding_multiple>")
        sys.exit(1)

    file_path = sys.argv[1]
    rounding_multiple = int(sys.argv[2])

    process_csv(file_path, rounding_multiple)
