use std::fmt::Debug;
use tokio_postgres::Row;

use super::EntityColumn;
use super::EntityDiff;
use super::EntityId;
use super::EntityMetadata;
use crate::query::NonNullTableAlias;
use crate::query::QueryBindings;

pub use petro_derive::Entity;

pub trait Entity: Debug + Clone + Sync + EntityMetadata {
    const ID_COLUMN: &'static EntityColumn;

    type EntityIdType: Entity;
    fn id(&self) -> &EntityId<Self::EntityIdType>;

    const VERSION_NUM_COLUMN: Option<&'static EntityColumn>;

    /// NOTE: returns `-1` if there's no version num column
    fn version(&self) -> i32;

    fn diff_entity(&self, other: &Self) -> EntityDiff<Self>;

    fn from_db_row(row: &Row, offset: usize) -> Self;
    fn bind_db_params_full<'a>(&'a self, bindings: &mut QueryBindings<'a>);
    fn bind_db_params_partial<'a>(
        &'a self,
        bindings: &mut QueryBindings<'a>,
        diff: &EntityDiff<Self>,
    );

    fn alias(alias: &'static str) -> NonNullTableAlias<Self> {
        return NonNullTableAlias::new(alias);
    }
}
