#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

// WGS84 标准椭球参数
#define WGS84_A     6378137.0
#define WGS84_F_INV 298.257223563
#define WGS84_F     (1.0 / WGS84_F_INV)
#define WGS84_E2    (2.0 * WGS84_F - WGS84_F * WGS84_F)

// 4字节 小端序解析
static int le32_to_cpu(const unsigned char *buf)
{
    return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
}

// 字符串 + 16进制
static void print_str_with_hex(const char *str, int len)
{
    int i;
    printf("'%.*s' [0x", len, str);
    for(i = 0; i < len; i++){
        printf("%02X", (unsigned char)str[i]);
    }
    printf("]");
}

// 单字节 + 16进制
static void print_u8_with_hex(unsigned char val)
{
    printf("%d [0x%02X]", val, val);
}

// 双字节 + 16进制
static void print_u16_with_hex(unsigned short val)
{
    printf("%d [0x%04X]", val, val);
}

// 4字节原始数组HEX
static void print_raw4_with_hex(const unsigned char *buf)
{
    printf("[0x%02X%02X%02X%02X]", buf[0], buf[1], buf[2], buf[3]);
}

// double(8字节) + 原始HEX
static void print_double_with_hex(double val)
{
    unsigned char *p = (unsigned char*)&val;
    printf("%.8lf [0x", val);
    printf("%02X%02X%02X%02X%02X%02X%02X%02X",
           p[7], p[6], p[5], p[4], p[3], p[2], p[1], p[0]);
    printf("]");
}

// float(4字节) + 原始HEX
static void print_float_with_hex(float val)
{
    unsigned char *p = (unsigned char*)&val;
    printf("%.3lf [0x", val);
    printf("%02X%02X%02X%02X", p[3], p[2], p[1], p[0]);
    printf("]");
}

// 经纬度(角度) → WGS84 地心地固 XYZ (高精度版)
static void llh2xyz(double lat_deg, double lon_deg, double h,
                    double *x, double *y, double *z)
{
    double B = lat_deg * M_PI / 180.0;
    double L = lon_deg * M_PI / 180.0;

    double sinB = sin(B);
    double cosB = cos(B);
    double sinL = sin(L);
    double cosL = cos(L);

    double N = WGS84_A / sqrt(1.0 - WGS84_E2 * sinB * sinB);
    *x = (N + h) * cosB * cosL;
    *y = (N + h) * cosB * sinL;
    *z = (N * (1.0 - WGS84_E2) + h) * sinB;
}

#pragma pack(1)
typedef struct RawBinHead512
{
    char head_info[53];
    char reserve0[5];

    unsigned char day;
    unsigned char mon;
    unsigned short year;

    char reserve1[18];

    double lat;
    double lon;
    float  alt;
    char   reserve3[4];

    unsigned char pos_unit;
    unsigned short ant_h_raw;

    char start_end[16];
    unsigned char ant_type_code;
    char reserve2[1];

    char ant_name[20];
    unsigned char ant_meas_mode;
    unsigned char ant_def_en;

    unsigned char edge_R_raw[4];
    unsigned char edge_H_raw[4];
    unsigned char HL1_raw[4];
    unsigned char HL2_raw[4];

    unsigned char freq_mode;
    unsigned char board_type;
    unsigned char rec_mode;

    char soft_ver[15];
    char marker_name[16];
    char marker_no[4];

    unsigned char ant_mask;
    char rec_info[20];
    char ant_sn[20];
    char observer[20];
    char agency[20];
    char marker_type[20];

    short de;
    short dn;

    char reserve_end[206];
} RawBinHead512;
#pragma pack()

int ReadBin512(const char *filepath, RawBinHead512 *out)
{
    FILE *fp = fopen(filepath, "rb");
    if (!fp)
    {
        perror("打开文件失败");
        return -1;
    }
    memset(out, 0, sizeof(RawBinHead512));
    size_t read_size = fread(out, 1, sizeof(RawBinHead512), fp);
    fclose(fp);

    printf("结构体实际大小: %zu 字节\n", sizeof(RawBinHead512));
    printf("读取字节数: %zu 字节\n\n", read_size);
    return 0;
}

void PrintBinHead(const RawBinHead512 *p)
{
    int edge_R  = le32_to_cpu(p->edge_R_raw);
    int edge_H  = le32_to_cpu(p->edge_H_raw);
    int HL1     = le32_to_cpu(p->HL1_raw);
    int HL2     = le32_to_cpu(p->HL2_raw);

    double X, Y, Z;
    // 强制转double计算高程，消除float精度损失
    llh2xyz(p->lat, p->lon, (double)p->alt, &X, &Y, &Z);

    printf("==================== 512字节二进制头解析结果 ====================\n");
    printf("头部标识: ");
    print_str_with_hex(p->head_info, sizeof(p->head_info));
    printf("\n");

    printf("采集日期: %04d-%02d-%02d [年:", p->year, p->mon, p->day);
    print_u16_with_hex(p->year);
    printf(" 月:");
    print_u8_with_hex(p->mon);
    printf(" 日:");
    print_u8_with_hex(p->day);
    printf("]\n");

    printf("坐标(经纬度+高程):\n");
    printf("  纬度: ");
    print_double_with_hex(p->lat);
    printf("\n");
    printf("  经度: ");
    print_double_with_hex(p->lon);
    printf("\n");
    printf("  高程: ");
    print_float_with_hex(p->alt);
    printf("\n");

    printf("APPROX POSITION XYZ:\n");
    printf("  X: %.4f m\n", X);
    printf("  Y: %.4f m\n", Y);
    printf("  Z: %.4f m\n", Z);
    printf("  XYZ: %.4f  %.4f  %.4f\n", X, Y, Z);

    printf("坐标单位: %s [", p->pos_unit == 0 ? "弧度" : "度");
    print_u8_with_hex(p->pos_unit);
    printf("]\n");

    printf("天线高原始值: ");
    print_u16_with_hex(p->ant_h_raw);
    printf(" mm\n");

    printf("起止时间: ");
    print_str_with_hex(p->start_end, sizeof(p->start_end));
    printf("\n");

    printf("天线类型编号: ");
    print_u8_with_hex(p->ant_type_code);
    printf("\n");

    printf("天线型号文本: ");
    print_str_with_hex(p->ant_name, sizeof(p->ant_name));
    printf("\n");

    const char *meas_mode_str[] = {
        "天线相位中心", "天线斜高方式", "天线垂直高(边缘)",
        "测高片", "天线垂直高(底部)"
    };
    printf("天线量取方式: %d (%s) [", p->ant_meas_mode,
           p->ant_meas_mode < 5 ? meas_mode_str[p->ant_meas_mode] : "未知");
    print_u8_with_hex(p->ant_meas_mode);
    printf("]\n");

    printf("天线参数启用: %s [", p->ant_def_en ? "是" : "否");
    print_u8_with_hex(p->ant_def_en);
    printf("]\n");

    printf("天线几何参数:\n");
    printf("  边缘半径R: %d mm ", edge_R);
    print_raw4_with_hex(p->edge_R_raw);
    printf("\n");
    printf("  边缘到底部距离H: %d mm ", edge_H);
    print_raw4_with_hex(p->edge_H_raw);
    printf("\n");
    printf("  L1相位中心到底部距离HL1: %d mm ", HL1);
    print_raw4_with_hex(p->HL1_raw);
    printf("\n");
    printf("  L2相位中心到底部距离HL2: %d mm ", HL2);
    print_raw4_with_hex(p->HL2_raw);
    printf("\n");

    printf("频点类型: %s [", p->freq_mode == 1 ? "单频" : "双频");
    print_u8_with_hex(p->freq_mode);
    printf("]\n");

    const char *board_str[] = {
        "无定义", "OEMV", "OEM4", "DATAGIRD", "HEMISPHERE(双频)",
        "JAVAD", "空", "UBLOX", "CSI(单频)", "BD970"
    };
    printf("GPS主板类型: %d (%s) [", p->board_type,
           p->board_type < 10 ? board_str[p->board_type] : "保留");
    print_u8_with_hex(p->board_type);
    printf("]\n");

    printf("接收机模式: %s [", p->rec_mode == 0 ? "静态/基准站" : "移动站");
    print_u8_with_hex(p->rec_mode);
    printf("]\n");

    printf("采集软件版本: ");
    print_str_with_hex(p->soft_ver, sizeof(p->soft_ver));
    printf("\n");

    printf("点名: ");
    print_str_with_hex(p->marker_name, sizeof(p->marker_name));
    printf("\n");
    printf("测站编号: ");
    print_str_with_hex(p->marker_no, sizeof(p->marker_no));
    printf("\n");

    printf("天线允许测量掩码: 0x%02X [", p->ant_mask);
    print_u8_with_hex(p->ant_mask);
    printf("]\n");
    if (p->ant_mask & 0x01) printf("  - 天线相位中心\n");
    if (p->ant_mask & 0x02) printf("  - 天线测高方式\n");
    if (p->ant_mask & 0x04) printf("  - 天线垂直测高\n");
    if (p->ant_mask & 0x08) printf("  - 测高片\n");
    if (p->ant_mask & 0x10) printf("  - 天线垂直高(底部)\n");

    printf("接收机厂家信息: ");
    print_str_with_hex(p->rec_info, sizeof(p->rec_info));
    printf("\n");
    printf("天线序列号: ");
    print_str_with_hex(p->ant_sn, sizeof(p->ant_sn));
    printf("\n");
    printf("观测者: ");
    print_str_with_hex(p->observer, sizeof(p->observer));
    printf("\n");
    printf("机构: ");
    print_str_with_hex(p->agency, sizeof(p->agency));
    printf("\n");
    printf("测站类型: ");
    print_str_with_hex(p->marker_type, sizeof(p->marker_type));
    printf("\n");

    printf("偏心量: 东向=");
    print_u16_with_hex((unsigned short)p->de);
    printf("mm, 北向=");
    print_u16_with_hex((unsigned short)p->dn);
    printf("mm\n");

    printf("================================================================\n");
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("用法: %s <二进制文件>\n", argv[0]);
        return 1;
    }
    RawBinHead512 hdr;
    ReadBin512(argv[1], &hdr);
    PrintBinHead(&hdr);
    return 0;
}