///
/// class: Club.cs
///
///This file contains the Club class, which manages the collection of devices in the polo club. 
///It provides methods to add, assign, return, and generate reports for devices, as well as retrieve all wearables.
///
/// Name: Rens Pastoor
/// Studentnumber: 555408
/// Date: 11 May 2025
///
///Version: 1
///
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;

namespace PoloClubApp 
{
    /// <summary>
    /// Represents a Polo Club that manages a collection of devices.
    /// </summary>
    class Club 
    {
        private string name;
        private List<Device> devices;

        /// <summary>
        /// Initializes a new instance of the Club class.
        /// </summary>
        /// <param name="name">The name of the club.</param>
        public Club(string name)
        {
            this.name = name;
            this.devices = new List<Device>();
        }

        /// <summary>
        /// Gets the name of the club (read-only).
        /// </summary>
        public string Name => this.name;

        // ----- Graded Methods -----

        /// <summary>
        /// Retrieves all wearable devices (implementing IWearable interface).
        /// </summary>
        /// <returns>List of wearable devices.</returns>
        public List<Device> GetAllWearables()
        {
            List<Device> wearables = new List<Device>();
            foreach (Device device in devices)
            {
                if (device is IWearable)
                {
                    wearables.Add(device);
                }
            }
            return wearables;
        }

        /// <summary>
        /// Assigns a device to a player.
        /// </summary>
        /// <param name="id">Device ID.</param>
        /// <param name="playerName">Player's name.</param>
        /// <exception cref="Exception">Thrown if device is not found.</exception>
        public void AssignDevice(int id, string playerName)
        {
            Device device = GetDeviceById(id) ?? throw new Exception("Device not found");
            int? waterResistance = (device as IWearable)?.GetWaterResistanceMeters();
            device.AssignDevice(playerName, waterResistance);
        }

        /// <summary>
        /// Returns a device from a player.
        /// </summary>
        /// <param name="id">Device ID.</param>
        /// <returns>True if successful, false if device not found.</returns>
        public bool ReturnDevice(int id)
        {
            Device device = GetDeviceById(id);
            return device?.ReturnDevice() ?? false;
        }

        /// <summary>
        /// Gets all devices assigned to a specific player.
        /// </summary>
        /// <param name="playerName">Player's name.</param>
        /// <returns>List of assigned devices.</returns>
        public List<Device> GetAllAssignedDevicesByPlayer(string playerName)
        {
            return devices.Where(d => d.PlayerName == playerName).ToList();
        }

        /// <summary>
        /// Generates a formatted device report for a player.
        /// </summary>
        /// <param name="playerName">Player's name.</param>
        /// <returns>Formatted report lines.</returns>
        public List<string> GenerateReportPerPlayer(string playerName)
        {
            List<Device> assignedDevices = GetAllAssignedDevicesByPlayer(playerName);
            List<string> report = new List<string>
            {
                $"List of devices assigned to {playerName}",
                "Phones",
                "-"
            };

            report.AddRange(assignedDevices
                .OfType<SmartPhone>()
                .Select(d => d.GetDetails()));

            report.AddRange(new[] { "Wearables", "-" });
            
            report.AddRange(assignedDevices
                .Where(d => d is IWearable)
                .Select(d => d.GetDetails()));

            report.Add($"Total: {assignedDevices.Count} devices, " +
                      $"{assignedDevices.Count(d => d is SmartPhone)} phones and " +
                      $"{assignedDevices.Count(d => d is IWearable)} wearables");

            return report;
        }

        // -----The provided code below will not be graded, therefore should not be changed-----

        /// <summary>
        /// Provides all devices to the caller.
        /// </summary>
        /// <returns>List of devices</returns>
        public List<Device> GetAllDevices(){
            return this.devices;
        }

        /// <summary>
        /// Adds a device to the list of devices if unique id is provided.
        /// </summary>
        /// <param name="device">device to be added</param>
        public void AddDevice(Device device) {
            foreach (Device dev in this.devices){
                if (dev.Id == device.Id){
                    return;
                }
            }
            devices.Add(device);
        }

        /// <summary>
        /// Provides a device by a given id.
        /// </summary>
        /// <param name="id">the unique identity number of the requested device.</param>
        /// <returns>A device when found, otherwise null</returns>
        public Device GetDeviceById(int id){
            foreach (Device dev in this.devices){
                if (dev.Id == id){
                    return dev;
                }
            }
            return null;
        }
    }
}

