// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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 std::sync::Arc;

use pyo3::{prelude::*, types::PyTuple};

use datafusion::arrow::array::{Array, ArrayRef};
use datafusion::arrow::datatypes::DataType;
use datafusion::arrow::pyarrow::{PyArrowConvert, PyArrowType};
use datafusion::common::ScalarValue;
use datafusion::error::{DataFusionError, Result};
use datafusion_expr::{
    create_udaf, Accumulator, AccumulatorFunctionImplementation, AggregateState, AggregateUDF,
};

use crate::expression::PyExpr;
use crate::utils::parse_volatility;

#[derive(Debug)]
struct RustAccumulator {
    accum: PyObject,
}

impl RustAccumulator {
    fn new(accum: PyObject) -> Self {
        Self { accum }
    }
}

impl Accumulator for RustAccumulator {
    fn state(&self) -> Result<Vec<AggregateState>> {
        let py_result: PyResult<Vec<ScalarValue>> =
            Python::with_gil(|py| self.accum.as_ref(py).call_method0("state")?.extract());
        match py_result {
            Ok(r) => Ok(r.into_iter().map(AggregateState::Scalar).collect()),
            Err(e) => Err(DataFusionError::Execution(format!("{}", e))),
        }
    }

    fn evaluate(&self) -> Result<ScalarValue> {
        Python::with_gil(|py| self.accum.as_ref(py).call_method0("evaluate")?.extract())
            .map_err(|e| DataFusionError::Execution(format!("{}", e)))
    }

    fn update_batch(&mut self, values: &[ArrayRef]) -> Result<()> {
        Python::with_gil(|py| {
            // 1. cast args to Pyarrow array
            let py_args = values
                .iter()
                .map(|arg| arg.data().to_owned().to_pyarrow(py).unwrap())
                .collect::<Vec<_>>();
            let py_args = PyTuple::new(py, py_args);

            // 2. call function
            self.accum
                .as_ref(py)
                .call_method1("update", py_args)
                .map_err(|e| DataFusionError::Execution(format!("{}", e)))?;

            Ok(())
        })
    }

    fn merge_batch(&mut self, states: &[ArrayRef]) -> Result<()> {
        Python::with_gil(|py| {
            let state = &states[0];

            // 1. cast states to Pyarrow array
            let state = state
                .data()
                .to_pyarrow(py)
                .map_err(|e| DataFusionError::Execution(format!("{}", e)))?;

            // 2. call merge
            self.accum
                .as_ref(py)
                .call_method1("merge", (state,))
                .map_err(|e| DataFusionError::Execution(format!("{}", e)))?;

            Ok(())
        })
    }

    fn size(&self) -> usize {
        std::mem::size_of_val(self)
    }
}

pub fn to_rust_accumulator(accum: PyObject) -> AccumulatorFunctionImplementation {
    Arc::new(move |_| -> Result<Box<dyn Accumulator>> {
        let accum = Python::with_gil(|py| {
            accum
                .call0(py)
                .map_err(|e| DataFusionError::Execution(format!("{}", e)))
        })?;
        Ok(Box::new(RustAccumulator::new(accum)))
    })
}

/// Represents an AggregateUDF
#[pyclass(name = "AggregateUDF", module = "datafusion", subclass)]
#[derive(Debug, Clone)]
pub struct PyAggregateUDF {
    pub(crate) function: AggregateUDF,
}

#[pymethods]
impl PyAggregateUDF {
    #[new(name, accumulator, input_type, return_type, state_type, volatility)]
    fn new(
        name: &str,
        accumulator: PyObject,
        input_type: PyArrowType<DataType>,
        return_type: PyArrowType<DataType>,
        state_type: PyArrowType<Vec<DataType>>,
        volatility: &str,
    ) -> PyResult<Self> {
        let function = create_udaf(
            name,
            input_type.0,
            Arc::new(return_type.0),
            parse_volatility(volatility)?,
            to_rust_accumulator(accumulator),
            Arc::new(state_type.0),
        );
        Ok(Self { function })
    }

    /// creates a new PyExpr with the call of the udf
    #[args(args = "*")]
    fn __call__(&self, args: Vec<PyExpr>) -> PyResult<PyExpr> {
        let args = args.iter().map(|e| e.expr.clone()).collect();
        Ok(self.function.call(args).into())
    }
}
