mod helpers;

use std::collections::{HashMap, HashSet};

use common::counter::hardware_counter::HardwareCounterCell;

use self::helpers::variable_retriever;
use super::StructPayloadIndexReadView;
use crate::common::operation_error::OperationResult;
use crate::id_tracker::IdTrackerRead;
use crate::index::field_index::FieldIndexRead;
use crate::index::query_optimization::payload_provider::PayloadProvider;
use crate::index::query_optimization::rescore_formula::value_retriever::VariableRetrieverFn;
use crate::json_path::JsonPath;
use crate::payload_storage::PayloadStorageRead;
use crate::vector_storage::VectorStorageRead;

impl<'a, P, I, V, F> StructPayloadIndexReadView<'a, P, I, V, F>
where
    P: PayloadStorageRead,
    I: IdTrackerRead,
    V: VectorStorageRead,
    F: FieldIndexRead,
{
    /// Prepares optimized functions to extract each of the variables, given a point id.
    pub(crate) fn retrievers_map<'b, 'q>(
        &'b self,
        variables: HashSet<JsonPath>,
        hw_counter: &'q HardwareCounterCell,
    ) -> OperationResult<HashMap<JsonPath, VariableRetrieverFn<'q>>>
    where
        'b: 'q,
    {
        let payload_provider = PayloadProvider::new(self.payload.clone());

        // prepare extraction of the variables from field indices or payload.
        let mut var_retrievers = HashMap::new();
        for key in variables {
            let payload_provider = payload_provider.clone();

            let retriever = variable_retriever(
                self.field_indexes,
                &key,
                payload_provider.clone(),
                hw_counter,
            )?;

            var_retrievers.insert(key, retriever);
        }

        Ok(var_retrievers)
    }
}
