import sys

import numpy as np
import serial
import serial.tools.list_ports

import config


# デバイス名でCOMポート番号を検索
def find_port(device_str):
    """
    Find the serial port from the device name.

    Parameters
    ----------
    device_str : str
        Device name string.

    Returns
    -------
    str
        Found serial port name or empty string if not found.
    """
    ports = list(serial.tools.list_ports.comports())
    found_list = list(filter(lambda x: device_str in x.description, ports))
    if len(found_list) == 0:
        return ""
    return found_list[0].device


# コマンド送受信
def send_command(ser, command):
    ser.write((command + "\r\n").encode())
    data = ser.read(1024)
    recv_items = [x.strip() for x in data.decode().split(",")]
    if recv_items[0] != config.CODE_OK:
        print(f"コマンド{command}に失敗しました")
        sys.exit()
    return recv_items


# メイン
if __name__ == "__main__":
    # COMポートを開く
    port = find_port(config.DEVICE_NAME)
    if port == "":
        print(f"COM port of {config.DEVICE_NAME} not found")
        sys.exit()
    ser = serial.Serial(port, config.BAUD_RATE, timeout=config.TIMEOUT)
    if not ser.is_open:
        print(f"COMポート{port}を開くことができませんでした")
        sys.exit()
    print(f"COMポート{port}が開きました")

    # 基本データ受信
    recv = send_command(ser, "IDR")
    wavelen = range(int(recv[5]), int(recv[6]) + 1, int(recv[7]))

    recv = send_command(ser, "STR")
    num_samples = int(recv[5])
    print(f"本体にあるサンプル数は{num_samples}個です")

    # 測定データ受信
    spectrum = []
    for i in range(num_samples):
        recv = send_command(ser, f"SDR,{i+1},{config.MEAS_TYPE_DICT[config.MEAS_TYPE]}")
        spectrum.append(recv[1:])
        print(".", end="")
    print("done")

    # COMポートを閉じる
    ser.close()

    # CSVファイルに保存
    spetrum_array = np.asarray(spectrum, dtype=np.float32) / 10000.0
    header_line = ",".join(map(str, wavelen))
    np.savetxt(
        config.SAVE_FILE,
        spetrum_array,
        delimiter=",",
        header=header_line,
        comments="",
        fmt="%.4f",
    )
