// SPDX-FileCopyrightText: Politik im Blick developers
// SPDX-FileCopyrightText: Wolfgang Silbermayr <wolfgang@silbermayr.at>
//
// SPDX-License-Identifier: AGPL-3.0-or-later OR EUPL-1.2

use oparl_types::{DateTime, Name, Url};
use pib_service_core_types::{BodyId, Entity, MeetingId, OrganizationId};
use serde::{Deserialize, Serialize};

pub mod by_id;
pub mod get;
pub mod post;

mod meeting_state;

pub use meeting_state::MeetingState;

use crate::Updatable;

#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub struct Meeting {
    pub organization_id: OrganizationId,
    pub name: Option<Name>,
    pub meeting_state: MeetingState,
    pub start: Option<DateTime>,
    pub end: Option<DateTime>,
    pub keyword: Option<Vec<String>>,
    pub license: Option<Url>,
    pub web: Option<Url>,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
pub struct MeetingParentId {
    pub body_id: BodyId,
}

impl Entity<MeetingParentId, MeetingId> for Meeting {}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UpdateMeeting {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub organization_id: Option<OrganizationId>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<Option<Name>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub meeting_state: Option<MeetingState>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub start: Option<Option<DateTime>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub end: Option<Option<DateTime>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub keyword: Option<Option<Vec<String>>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub license: Option<Option<Url>>,

    #[serde(skip_serializing_if = "Option::is_none")]
    pub web: Option<Option<Url>>,
}

impl Updatable for Meeting {
    type Update = UpdateMeeting;

    fn build_update_from(
        &self,
        Self {
            organization_id,
            name,
            meeting_state,
            start,
            end,
            keyword,
            license,
            web,
        }: &Self,
    ) -> Self::Update {
        let organization_id = self.organization_id.build_update_from(organization_id);
        let name = self.name.build_update_from(name);
        let meeting_state = self.meeting_state.build_update_from(meeting_state);
        let start = self.start.build_update_from(start);
        let end = self.end.build_update_from(end);
        let keyword = self.keyword.build_update_from(keyword);
        let license = self.license.build_update_from(license);
        let web = self.web.build_update_from(web);

        Self::Update {
            organization_id,
            name,
            meeting_state,
            start,
            end,
            keyword,
            license,
            web,
        }
    }
}
