// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use crate::scene::facets::FacetId;
use crate::scene::layout::ArrangerPtr;
use crate::scene::scene::Scene;
use crate::{IdFromRaw, IdGenerator2, Size};
use std::any::Any;
use std::collections::HashMap;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
/// Identifier for a group.
pub struct GroupId(u64);

impl GroupId {
    /// Create a new group identifier.
    pub(crate) fn new() -> Self {
        IdGenerator2::<GroupId>::next().expect("group_id")
    }
}

impl IdFromRaw for GroupId {
    fn from_raw(id: u64) -> GroupId {
        GroupId(id)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) enum GroupMember {
    Facet(FacetId),
    Group(GroupId),
}

/// Dynamic type for data an arranger might want to keep per group
/// member.
pub type GroupMemberData = Box<dyn Any>;

impl GroupMember {
    fn is_facet(&self, facet_id: FacetId) -> bool {
        match self {
            GroupMember::Group(_) => false,
            GroupMember::Facet(member_facet_id) => *member_facet_id == facet_id,
        }
    }
}

#[derive(Debug)]
pub(crate) struct GroupEntry {
    member: GroupMember,
    member_data: Option<GroupMemberData>,
}

#[derive(Debug)]
pub(crate) struct Group {
    // TODO(https://fxbug.dev/42165549)
    #[allow(unused)]
    pub id: GroupId,
    // TODO(https://fxbug.dev/42165549)
    #[allow(unused)]
    pub label: String,
    pub members: Vec<GroupEntry>,
    pub arranger: Option<ArrangerPtr>,
}

#[derive(Debug)]
pub(crate) struct GroupMap {
    root_group_id: Option<GroupId>,
    map: HashMap<GroupId, Group>,
}

impl GroupMap {
    pub fn new() -> Self {
        let map = HashMap::new();
        Self { root_group_id: None, map }
    }

    pub fn get_root_group_id(&self) -> GroupId {
        self.root_group_id.expect("root_group_id")
    }

    pub fn add_facet_to_group(
        &mut self,
        facet_id: FacetId,
        group_id: GroupId,
        member_data: Option<GroupMemberData>,
    ) {
        let group = self.map.get_mut(&group_id).expect("group");

        group.members.push(GroupEntry { member: GroupMember::Facet(facet_id), member_data });
    }

    pub fn remove_facet_from_group(&mut self, facet_id: FacetId, group_id: GroupId) {
        let group = self.map.get_mut(&group_id).expect("group");
        group.members.retain(|entry| !entry.member.is_facet(facet_id));
    }

    pub fn group_members(&self, group_id: GroupId) -> Vec<GroupMember> {
        self.map
            .get(&group_id)
            .expect("group_id")
            .members
            .iter()
            .map(|entry| entry.member)
            .collect()
    }

    pub(crate) fn group_member_data(&self, group_id: GroupId) -> Vec<&Option<GroupMemberData>> {
        let member_data = self
            .map
            .get(&group_id)
            .expect("group_id")
            .members
            .iter()
            .map(|entry| &entry.member_data)
            .collect();
        member_data
    }

    pub fn group_arranger(&self, group_id: GroupId) -> Option<&ArrangerPtr> {
        self.map.get(&group_id).and_then(|group| group.arranger.as_ref())
    }

    pub fn set_group_arranger(&mut self, group_id: GroupId, group_arranger: ArrangerPtr) {
        let group = self.map.get_mut(&group_id).expect("group");
        group.arranger = Some(group_arranger);
    }

    pub fn start_group(
        &mut self,
        group_id: GroupId,
        label: &str,
        arranger: ArrangerPtr,
        parent: Option<&GroupId>,
        member_data: Option<GroupMemberData>,
    ) {
        if self.root_group_id.is_none() {
            self.root_group_id = Some(group_id);
        }
        let group = Group {
            id: group_id,
            label: String::from(label),
            members: Vec::new(),
            arranger: Some(arranger),
        };
        self.map.insert(group_id, group);
        if let Some(parent) = parent {
            let group = self.map.get_mut(&parent).expect("group");
            group.members.push(GroupEntry { member: GroupMember::Group(group_id), member_data });
        }
    }

    fn calculate_size_map_internal(
        &self,
        target_size: &Size,
        scene: &Scene,
        group_id: &GroupId,
        size_map: &mut HashMap<GroupMember, Size>,
    ) -> Size {
        let group_members = self.group_members(*group_id);
        let mut member_sizes = Vec::new();
        for member in group_members.iter() {
            match member {
                GroupMember::Group(member_group_id) => {
                    let size = self.calculate_size_map_internal(
                        target_size,
                        scene,
                        &member_group_id,
                        size_map,
                    );
                    size_map.insert(*member, size);
                    member_sizes.push(size);
                }
                GroupMember::Facet(member_facet_id) => {
                    let size = scene.calculate_facet_size(&member_facet_id, *target_size);
                    member_sizes.push(size);
                    size_map.insert(*member, size);
                }
            }
        }
        let optional_arranger = self.group_arranger(*group_id);
        if let Some(arranger) = optional_arranger {
            let member_data = self.group_member_data(*group_id);
            let mut mut_sizes = member_sizes.clone();
            let arranged_size = arranger.calculate_size(*target_size, &mut mut_sizes, &member_data);
            for ((member_id, member_size), new_member_size) in
                group_members.iter().zip(member_sizes.iter()).zip(mut_sizes.iter())
            {
                if member_size != new_member_size {
                    size_map.insert(*member_id, *new_member_size);
                }
            }
            arranged_size
        } else {
            panic!("need an arranger");
        }
    }

    pub fn calculate_size_map(
        &self,
        target_size: Size,
        scene: &Scene,
    ) -> HashMap<GroupMember, Size> {
        let mut size_map = HashMap::new();
        let root_group_id = self.root_group_id.expect("root_group_id");
        let root_size =
            self.calculate_size_map_internal(&target_size, scene, &root_group_id, &mut size_map);
        size_map.insert(GroupMember::Group(root_group_id), root_size);
        size_map
    }
}
