// 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::fmt::{self, Display, Formatter};

use datafusion::logical_expr::logical_plan::Explain;
use datafusion::logical_expr::LogicalPlan;
use pyo3::prelude::*;
use pyo3::IntoPyObjectExt;

use super::logical_node::LogicalNode;
use crate::common::df_schema::PyDFSchema;
use crate::errors::py_type_err;
use crate::sql::logical::PyLogicalPlan;

#[pyclass(frozen, name = "Explain", module = "datafusion.expr", subclass)]
#[derive(Clone)]
pub struct PyExplain {
    explain: Explain,
}

impl From<PyExplain> for Explain {
    fn from(explain: PyExplain) -> Self {
        explain.explain
    }
}

impl From<Explain> for PyExplain {
    fn from(explain: Explain) -> PyExplain {
        PyExplain { explain }
    }
}

impl Display for PyExplain {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(
            f,
            "Explain
            verbose: {:?}
            plan: {:?}
            stringified_plans: {:?}
            schema: {:?}
            logical_optimization_succeeded: {:?}",
            &self.explain.verbose,
            &self.explain.plan,
            &self.explain.stringified_plans,
            &self.explain.schema,
            &self.explain.logical_optimization_succeeded
        )
    }
}

#[pymethods]
impl PyExplain {
    fn explain_string(&self) -> PyResult<Vec<String>> {
        let mut string_plans: Vec<String> = Vec::new();
        for stringified_plan in &self.explain.stringified_plans {
            string_plans.push((*stringified_plan.plan).clone());
        }
        Ok(string_plans)
    }

    fn verbose(&self) -> bool {
        self.explain.verbose
    }

    fn plan(&self) -> PyResult<PyLogicalPlan> {
        Ok(PyLogicalPlan::from((*self.explain.plan).clone()))
    }

    fn schema(&self) -> PyDFSchema {
        (*self.explain.schema).clone().into()
    }

    fn logical_optimization_succceeded(&self) -> bool {
        self.explain.logical_optimization_succeeded
    }
}

impl TryFrom<LogicalPlan> for PyExplain {
    type Error = PyErr;

    fn try_from(logical_plan: LogicalPlan) -> Result<Self, Self::Error> {
        match logical_plan {
            LogicalPlan::Explain(explain) => Ok(PyExplain { explain }),
            _ => Err(py_type_err("unexpected plan")),
        }
    }
}

impl LogicalNode for PyExplain {
    fn inputs(&self) -> Vec<PyLogicalPlan> {
        vec![]
    }

    fn to_variant<'py>(&self, py: Python<'py>) -> PyResult<Bound<'py, PyAny>> {
        self.clone().into_bound_py_any(py)
    }
}
