package com.seismic.service;

import com.seismic.model.SeismicMetadata;
import org.springframework.stereotype.Service;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpRange;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;

@Service
public class SeismicDataService {
    
    private final ResourceLoader resourceLoader;
    
    @Value("${seismic.data.path}")
    private String seismicDataPath;
    
    public SeismicDataService(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public SeismicMetadata getMetadata(String fileName) throws IOException {
        File segyFile = new File(seismicDataPath + fileName);
        try (RandomAccessFile raf = new RandomAccessFile(segyFile, "r")) {
            // 读取SEGY文件头
            byte[] binaryHeader = new byte[400];
            raf.seek(3200); // 跳过文本头
            raf.read(binaryHeader);
            
            // 解析二进制头
            ByteBuffer buffer = ByteBuffer.wrap(binaryHeader);
            buffer.order(ByteOrder.BIG_ENDIAN);
            
            // 获取采样间隔（微秒）
            buffer.position(16);
            int sampleInterval = buffer.getShort() & 0xFFFF;
            
            // 获取每道采样数
            buffer.position(20);
            int samplesPerTrace = buffer.getShort() & 0xFFFF;
            
            // 获取数据格式代码
            buffer.position(24);
            int formatCode = buffer.getShort() & 0xFFFF;
            
            // 计算道数
            long fileSize = segyFile.length();
            int traceHeaderSize = 240;
            int traceSampleSize = 4; // 假设是4字节浮点数
            int traceSize = traceHeaderSize + (samplesPerTrace * traceSampleSize);
            int traces = (int)((fileSize - 3600) / traceSize);
            
            // 计算统计信息
            double min = Double.MAX_VALUE;
            double max = Double.MIN_VALUE;
            double sumSquares = 0;
            long sampleCount = 0;
            
            byte[] traceData = new byte[samplesPerTrace * 4];
            for (int i = 0; i < Math.min(traces, 1000); i++) { // 只读取前1000道以提高性能
                raf.seek(3600 + (i * traceSize) + traceHeaderSize);
                raf.read(traceData);
                ByteBuffer traceBuffer = ByteBuffer.wrap(traceData);
                traceBuffer.order(ByteOrder.BIG_ENDIAN);
                
                for (int j = 0; j < samplesPerTrace; j++) {
                    float value = traceBuffer.getFloat(j * 4);
                    min = Math.min(min, value);
                    max = Math.max(max, value);
                    sumSquares += value * value;
                    sampleCount++;
                }
            }
            
            double rms = Math.sqrt(sumSquares / sampleCount);
            
            // 构建元数据对象
            return SeismicMetadata.builder()
                .dimensions(SeismicMetadata.Dimensions.builder()
                    .traces(traces)
                    .samples(samplesPerTrace)
                    .build())
                .statistics(SeismicMetadata.Statistics.builder()
                    .min(min)
                    .max(max)
                    .rms(rms)
                    .build())
                .sampleInfo(SeismicMetadata.SampleInfo.builder()
                    .interval(sampleInterval)
                    .format(getFormatString(formatCode))
                    .unit("ms")
                    .build())
                .build();
        }
    }
    
    public byte[] getSeismicData(String fileName, List<HttpRange> ranges) throws IOException {
        File segyFile = new File(seismicDataPath + fileName);
        
        if (ranges == null || ranges.isEmpty()) {
            // 如果没有指定范围，返回整个文件
            try (FileInputStream fis = new FileInputStream(segyFile)) {
                return fis.readAllBytes();
            }
        } else {
            // 处理范围请求
            HttpRange range = ranges.get(0); // 只处理第一个范围
            long start = range.getRangeStart(segyFile.length());
            long end = range.getRangeEnd(segyFile.length());
            int length = (int)(end - start + 1);
            
            byte[] data = new byte[length];
            try (RandomAccessFile raf = new RandomAccessFile(segyFile, "r")) {
                raf.seek(start);
                raf.read(data);
                return data;
            }
        }
    }
    
    private String getFormatString(int formatCode) {
        switch (formatCode) {
            case 1: return "IBM浮点数";
            case 2: return "32位定点数";
            case 3: return "16位定点数";
            case 4: return "带增益码的定点数";
            case 5: return "IEEE浮点数";
            default: return "未知格式";
        }
    }
} 