/* 
 * Copyright (c)2009-2025 DemiVision, LLC. All Rights Reserved. The information 
 * herein is the CONFIDENTIAL and PROPRIETARY information of DemiVision, LLC. 
 */

using Plugin.Firebase.Firestore;

using DXLib.UI;
using DXLib.Utils;

namespace iStatVball3;

/*
 * Represents the venue (gym, school, etc) for a match.
 */
public class Venue : RootModel
{
	/* Constants */
	public const string CollectionKey = "Venues";

	// Available court types
	public const string DefaultKey = "default";
	public const string WoodKey = "wood";
	public const string TileKey = "tile";

	// Colors if not user defined
	public static readonly Color DefaultLineColor = DXColors.Light4;
	public static readonly Color DefaultInnerColor = DXColors.Negative;
	public static readonly Color DefaultOuterColor = DXColors.Action;

    /* Properties */

    // Required
    [FirestoreProperty("Name")] public string Name { get; set; }

    // Optional
    [FirestoreProperty("Description")] public string Description { get; set; }
    [FirestoreProperty("Location")] public string Location { get; set; }
    [FirestoreProperty("Notes")] public string Notes { get; set; }

    // Record
    [FirestoreProperty("Won")] public int Won { get; set; }
    [FirestoreProperty("Lost")] public int Lost { get; set; }
    [FirestoreProperty("Tied")] public int Tied { get; set; }

    // Court customization
    [FirestoreProperty("CourtType")] public string CourtType { get; set; }

    [FirestoreProperty("LineColorValue")] public long? LineColorValue { get; set; }
    [FirestoreProperty("InnerColorValue")] public long? InnerColorValue { get; set; }
    [FirestoreProperty("OuterColorValue")] public long? OuterColorValue { get; set; }

    // Parent (FK)
    [FirestoreProperty("SeasonId")] public string SeasonId { get; set; }

	/* Ignored */
	public override string ObjectName => Name;

	// Colors
	public Color LineColor
	{
		get => LineColorValue.HasValue ? Color.FromUint( (uint)LineColorValue ) : DefaultLineColor;
		set => LineColorValue = value.ToUint();
	}

	public Color InnerColor
	{
		get => InnerColorValue.HasValue ? Color.FromUint( (uint)InnerColorValue.Value ) : DefaultInnerColor;
		set => InnerColorValue = value.ToUint();
	}

	public Color OuterColor
	{
		get => OuterColorValue.HasValue ? Color.FromUint( (uint)OuterColorValue.Value ) : DefaultOuterColor;
		set => OuterColorValue = value.ToUint();
	}

	// Parent
	public Season Season { get; set; }

	/* Methods */
	public Venue()
	{
		BaseCollectionKey = CollectionKey;

		// Defaults
		CourtType = DefaultKey;

		LineColorValue = DefaultLineColor.ToUint();
		InnerColorValue = DefaultInnerColor.ToUint();
		OuterColorValue = DefaultOuterColor.ToUint();
	}

	// Tests equality based on unique ID
	public override bool Equals( object obj )
	{
		return (obj is Venue venue) && venue.UniqueId.Equals( UniqueId );
	}

	// Generates unique hash code for lists
	public override int GetHashCode()
	{
		return UniqueId.GetHashCode();
	}

	/* Permissions */

	// Determines if user has permission to create Venues
	public static bool CanCreate( Season season, User user )
	{
		return user.Level switch
		{
			// Director/coach/stat always can
			User.LevelType.Director or 
			User.LevelType.Coach or 
			User.LevelType.Statistician => !season.IsSample || user.IsAdmin,
			
			// No-one else can
			_ => false
		};
	}

	// Determines if user has permission to edit Venues
	public static bool CanEdit( User user )
	{
		return user.Level switch
		{
			// Director/coach/stat always can
			User.LevelType.Director or 
			User.LevelType.Coach or 
			User.LevelType.Statistician => true,
			
			// No-one else can
			_ => false
		};
	}

	// Determines if user has permission to analyze Venue stats
	public bool CanAnalyze( User user )
	{
		return user.Level switch
		{
			// Only Director/Coach
			User.LevelType.Director or 
			User.LevelType.Coach => true,
			
			// No-one else
			_ => Season.IsSample
		};
	}

    /* Analyze */

	// Returns list of all matches played in this Venue
	public List<Match> GetMatches()
	{
	   List<Match> matches = [];
	   List<Match> matchList = Season.GetMatches();
	
	   // Only include matches for this venue
	   foreach ( Match match in matchList )
	   {
		   if ( (match.Venue != null) && match.Venue.Equals( this ) )
		   {
				matches.Add( match );
		   }
	   }
	
	   return matches;
	}
	
	// Aggregates all data for analyzing scope of this Venue
	public async Task<DataStats> Aggregate()
	{
		DataStats stats = new();
		List<Match> matches = GetMatches();
	
		// Append stats from all matches for venue
		foreach ( Match match in matches )
		{
			stats.Add( await match.Aggregate() );
		}
	
		return stats;
	}
	
	// Aggregates all raw summary data for scope of this Venue
	public StatSummary AggregateRaw()
	{
		StatSummary summary = new();
		List<Match> matches = GetMatches();
	
		// Aggregate summary data for all matches for venue
		foreach ( Match match in matches )
		{
			summary.Add( match.AggregateRaw() );
		}
	
		return summary;
	}

	/* CRUD */

	// Updates won/lost/tied fields for this object (batched)
	public void UpdateRecord( IWriteBatch batch )
	{
		Won = 0; 
		Lost = 0; 
		Tied = 0;

		// Recount all matches
		foreach ( Match match in Season.Matches.Where( match => (match.Venue != null) && match.Venue.Equals( this ) ) )
		{
			if ( match.Won )
			{
				Won++;
			}
			else if ( match.Lost )
			{
				Lost++;
			}
			else if ( match.Tied )
			{
				Tied++;
			}
		}

		// Persist
		Update( batch, "Won", Won );
		Update( batch, "Lost", Lost );
		Update( batch, "Tied", Tied );
	}

	// Updates RallyFlow court texture/colors for specified venue
	public static async Task UpdateCourt( CourtView court, Venue venue )
	{
		bool hasVenue = (venue != null);

		// Use default colors if no venue specified
		Color line = hasVenue ? venue.LineColor : DefaultLineColor;
		Color inner = hasVenue ? venue.InnerColor : DefaultInnerColor;
		Color outer = hasVenue ? venue.OuterColor : DefaultOuterColor;

		string texture = null;

		// Optional wood texture
		if ( hasVenue && (venue.CourtType == WoodKey) )
		{
			texture = DXDevice.IsLandscape() ? "wood_horiz.jpg" : "wood_vert.jpg";
		}

		await court.Customize( texture, line, inner, outer );
	}

	// Performs cascading delete for this Venue
	public override async Task Delete( bool remove = true )
	{
		// No children to delete

		// Remove from parent
		if ( remove )
		{
			Season.Venues.Remove( this );
		}

		// Delete self
		await base.Delete( remove );
	}

	/* Import */

	// Creates new Venue in specified season from existing object (batched)
	public static void Import( IWriteBatch batch, Season season, Venue venue )
	{
		Venue newVenue = new()
		{
			// Copy fields from existing object
			Name = venue.Name,

			Description = venue.Description,
			Location = venue.Location,
			Notes = venue.Notes,

			CourtType = venue.CourtType,
			LineColorValue = venue.LineColorValue,
			InnerColorValue = venue.InnerColorValue,
			OuterColorValue = venue.OuterColorValue,

			// Start with existing image
			ImageUrl = venue.ImageUrl,

			// Connect to this season
			SeasonId = season.UniqueId,
			Season = season
		};

		// Add to parent
		season.Venues.Add( newVenue );

		// Connect roots
		newVenue.Connect( batch, venue );

		// Persist
		newVenue.Create( batch );
	}
}

//
