//
//  Copyright 2025-2026 Shuntaro Kasatani
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

use crate::{
    ast::Range,
    error::{EK, ErrorCollector, Phase, Pl, Sv},
};

impl ErrorCollector {
    pub(crate) fn prefix_op_not_defined(&mut self, range: Range, phase: Phase, symbol: &str) {
        self.emit(
            EK::PrefixOpNotDefined,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![symbol.to_string()]),
        );
    }

    pub(crate) fn infix_or_postfix_op_not_defined(
        &mut self,
        range: Range,
        phase: Phase,
        symbol: &str,
    ) {
        self.emit(
            EK::InfixOrPostfixOpNotDefined,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![symbol.to_string()]),
        );
    }

    pub(crate) fn infix_op_not_found(
        &mut self,
        range: Range,
        phase: Phase,
        symbol: &str,
        left_type: &str,
        right_type: &str,
    ) {
        self.emit(
            EK::InfixOpNotFound,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![
                symbol.to_string(),
                left_type.to_string(),
                right_type.to_string(),
            ]),
        );
    }

    pub(crate) fn prefix_op_not_found(
        &mut self,
        range: Range,
        phase: Phase,
        symbol: &str,
        operand_type: &str,
    ) {
        self.emit(
            EK::PrefixOpNotFound,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![symbol.to_string(), operand_type.to_string()]),
        );
    }

    pub(crate) fn postfix_op_not_found(
        &mut self,
        range: Range,
        phase: Phase,
        symbol: &str,
        operand_type: &str,
    ) {
        self.emit(
            EK::PostfixOpNotFound,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![symbol.to_string(), operand_type.to_string()]),
        );
    }

    pub(crate) fn op_not_associative(&mut self, range: Range, phase: Phase, symbol: &str) {
        self.emit(
            EK::OpNotAssociative,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![symbol.to_string()]),
        );
    }

    pub(crate) fn wrong_param_count_for_infix(
        &mut self,
        range: Range,
        phase: Phase,
        op_symbol: &str,
        param_count: usize,
    ) {
        self.emit(
            EK::WrongParamCountForInfix,
            range,
            phase,
            Sv::Error,
            Pl::StrAndNum(op_symbol.to_string(), param_count),
        );
    }

    pub(crate) fn wrong_param_count_for_prefix(
        &mut self,
        range: Range,
        phase: Phase,
        op_symbol: &str,
        param_count: usize,
    ) {
        self.emit(
            EK::WrongParamCountForPrefix,
            range,
            phase,
            Sv::Error,
            Pl::StrAndNum(op_symbol.to_string(), param_count),
        );
    }

    pub(crate) fn wrong_param_count_for_postfix(
        &mut self,
        range: Range,
        phase: Phase,
        op_symbol: &str,
        param_count: usize,
    ) {
        self.emit(
            EK::WrongParamCountForPostfix,
            range,
            phase,
            Sv::Error,
            Pl::StrAndNum(op_symbol.to_string(), param_count),
        );
    }

    pub(crate) fn duplicate_infix_define(&mut self, range: Range, phase: Phase, op_symbol: &str) {
        self.emit(
            EK::DuplicateInfixDefine,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![op_symbol.to_string()]),
        );
    }

    pub(crate) fn duplicate_prefix_define(&mut self, range: Range, phase: Phase, op_symbol: &str) {
        self.emit(
            EK::DuplicatePrefixDefine,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![op_symbol.to_string()]),
        );
    }

    pub(crate) fn duplicate_postfix_define(&mut self, range: Range, phase: Phase, op_symbol: &str) {
        self.emit(
            EK::DuplicatePostfixDefine,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![op_symbol.to_string()]),
        );
    }

    pub(crate) fn duplicate_infix_func(
        &mut self,
        range: Range,
        phase: Phase,
        op_symbol: &str,
        lhs_type: String,
        rhs_type: String,
    ) {
        self.emit(
            EK::DuplicateInfixFunc,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![op_symbol.to_string(), lhs_type, rhs_type]),
        );
    }

    pub(crate) fn duplicate_prefix_func(
        &mut self,
        range: Range,
        phase: Phase,
        op_symbol: &str,
        operand_type: String,
    ) {
        self.emit(
            EK::DuplicatePrefixFunc,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![op_symbol.to_string(), operand_type]),
        );
    }

    pub(crate) fn duplicate_postfix_func(
        &mut self,
        range: Range,
        phase: Phase,
        op_symbol: &str,
        operand_type: String,
    ) {
        self.emit(
            EK::DuplicatePostfixFunc,
            range,
            phase,
            Sv::Error,
            Pl::StrVec(vec![op_symbol.to_string(), operand_type]),
        );
    }
}
