// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2025 rhythmcache
// https://github.com/rhythmcache/payload-dumper-rust

use crate::payload::payload_dumper::{AsyncPayloadRead, PayloadReader};
use anyhow::Result;
use async_trait::async_trait;
use std::path::PathBuf;
use std::pin::Pin;
use tokio::fs::File;
use tokio::io::AsyncSeekExt;
use tokio::io::{AsyncRead, AsyncReadExt, BufReader};

pub struct LocalAsyncPayloadReader {
    path: PathBuf,
}

impl LocalAsyncPayloadReader {
    pub async fn new(path: PathBuf) -> Result<Self> {
        File::open(&path).await?;
        Ok(Self { path })
    }
}

#[async_trait]
impl AsyncPayloadRead for LocalAsyncPayloadReader {
    async fn open_reader(&self) -> Result<Box<dyn PayloadReader>> {
        let file = File::open(&self.path).await?;
        Ok(Box::new(LocalPayloadReader {
            file: BufReader::new(file),
        }))
    }
}

struct LocalPayloadReader {
    file: BufReader<File>,
}

#[async_trait]
impl PayloadReader for LocalPayloadReader {
    async fn read_range(
        &mut self,
        offset: u64,
        length: u64,
    ) -> Result<Pin<Box<dyn AsyncRead + Send + '_>>> {
        self.file.seek(std::io::SeekFrom::Start(offset)).await?;
        Ok(Box::pin((&mut self.file).take(length)))
    }
}
