// Copyright (C) 2024 Quickwit, Inc.
//
// Quickwit is offered under the AGPL v3.0 and as commercial software.
// For commercial licensing, contact us at hello@quickwit.io.
//
// AGPL:
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

use std::fmt;

use quickwit_metastore::SplitMaturity;

use crate::merge_policy::MergePolicy;

/// The NopMergePolicy, as the name suggests, is no-op and does not perform any merges.
/// <https://en.wikipedia.org/wiki/NOP_(code)>
#[derive(Debug)]
pub struct NopMergePolicy;

impl fmt::Display for NopMergePolicy {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{self:?}")
    }
}

impl MergePolicy for NopMergePolicy {
    fn operations(
        &self,
        _splits: &mut Vec<quickwit_metastore::SplitMetadata>,
    ) -> Vec<super::MergeOperation> {
        Vec::new()
    }

    fn split_maturity(&self, _split_num_docs: usize, _split_num_merge_ops: usize) -> SplitMaturity {
        // With the no merge policy, all splits are mature immediately as they will never undergo
        // any merge.
        SplitMaturity::Mature
    }
}

#[cfg(test)]
mod tests {

    use quickwit_metastore::SplitMaturity;

    use crate::merge_policy::{MergePolicy, NopMergePolicy};

    #[test]
    pub fn test_no_merge_policy_maturity_timestamp() {
        // All splits are always mature for `NopMergePolicy`.
        assert_eq!(NopMergePolicy.split_maturity(10, 0), SplitMaturity::Mature);
    }

    #[test]
    pub fn test_no_merge_policy_operations() {
        let mut splits = super::super::tests::create_splits(&NopMergePolicy, vec![1; 100]);
        assert!(NopMergePolicy.operations(&mut splits).is_empty());
        assert_eq!(splits.len(), 100);
    }
}
