using DominionBase;
using DominionBase.Cards;
using DominionBase.Enums;
using DominionBase.Piles;
using DominionBase.Players;
using DominionBase.Utilities;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using CtrlOrientation = System.Windows.Controls.Orientation;
namespace Dominion.NET_WPF
{
///
/// Interaction logic for CardCollectionControl.xaml
///
public partial class CardCollectionControl : UserControl
{
public static readonly DependencyProperty SplitAtProperty =
DependencyProperty.Register("SplitAt", typeof(Func), typeof(CardCollectionControl), new PropertyMetadata(null));
public Func SplitAt
{
get { return (Func)GetValue(SplitAtProperty); }
set
{
SetValue(SplitAtProperty, value);
UpdateCardDisplay();
}
}
public static readonly DependencyProperty MinStackWidthProperty =
DependencyProperty.Register("MinStackWidth", typeof(double), typeof(CardCollectionControl), new PropertyMetadata(0d));
public double MinStackWidth
{
get { return (double)GetValue(MinStackWidthProperty); }
set
{
SetValue(MinStackWidthProperty, value);
UpdateCardDisplay();
}
}
private CardSize _cardSize = CardSize.Text;
private IEnumerable _cardPile = new DisplayableCollection();
private Dictionary _tokenDict;
private const int GlowSize = 20;
private string _pileName = "Pile Name";
private bool _displayEmptyPile;
private IPlayer _player;
private PhaseEnum _playerPhase = PhaseEnum.Action;
private PlayerMode _playerMode = PlayerMode.Waiting;
private bool _isClickable;
public CardCollectionControl()
{
InitializeComponent();
CardSize = CardSize.Medium;
IsClickable = false;
var gs = GlowSize / 2d;
wpCardCollections.Margin = new Thickness(gs, gs, gs, 0);
wpCardCollections2.Margin = new Thickness(gs, gs, gs, 0);
}
public IDisplayable ClickedCard { get; } = null;
public CtrlOrientation Orientation { get; set; } = CtrlOrientation.Horizontal;
public HorizontalAlignment CardHorizontalAlignment { get; set; } = HorizontalAlignment.Left;
public bool ExactCount { get; set; }
public bool IsCardsVisible { get; set; }
public bool IsClickable
{
get
{
return _isClickable;
}
set
{
_isClickable = value;
foreach (var csc in wpCardCollections.Children.OfType())
csc.IsClickable = value;
foreach (var csc in wpCardCollections2.Children.OfType())
csc.IsClickable = value;
}
}
public bool IsDisplaySorted { get; set; }
public bool IsVPsVisible { get; set; }
public bool DisplayEmptyPile
{
get { return _displayEmptyPile; }
set
{
_displayEmptyPile = value;
if (Pile == null || PileCount == 0)
UpdateCardDisplay();
}
}
public CardSize CardSize
{
get { return _cardSize; }
set
{
_cardSize = value;
UpdateCardDisplay();
}
}
public IEnumerable Pile
{
get { return _cardPile; }
set
{
_cardPile = value ?? new DisplayableCollection();
UpdateCardDisplay();
}
}
public Dictionary TokenDict
{
private get { return _tokenDict; }
set
{
_tokenDict = value;
UpdateCardDisplay();
}
}
public DominionBase.Piles.Visibility PileVisibility
{
get
{
var pile = Pile as CardPile;
return pile?.Visibility ?? DominionBase.Piles.Visibility.All;
}
}
private int PileCount
{
get
{
var pile = Pile as CardPile;
return pile?.Count ?? Pile.Count();
}
}
public string PileName
{
get { return _pileName; }
set
{
_pileName = value;
UpdateCardDisplay();
}
}
public void UpdateCardDisplay()
{
wpCardCollections.Children.Clear();
wpCardCollections2.Children.Clear();
wpToolTipCards.Children.Clear();
nPileName.Content = PileName;
if (CardSize == CardSize.Full && Pile != null && PileCount > 0)
{
foreach (var card in Pile)
{
var ttd = new ToolTipIDisplayable
{
Card = card,
Margin = new Thickness(3)
};
wpToolTipCards.Children.Add(ttd);
}
}
else
{
nPileName.Visibility = string.IsNullOrEmpty(PileName) ? System.Windows.Visibility.Collapsed : System.Windows.Visibility.Visible;
if (ExactCount && Pile != null && PileCount > 0)
{
lCount.Visibility = System.Windows.Visibility.Visible;
lCount.Content = $"({StringUtility.Plural("Card", PileCount, true)})";
}
else
{
lCount.Visibility = System.Windows.Visibility.Collapsed;
}
var currentWrapPanel = wpCardCollections;
foreach (var cardStack in GenerateCardStacks())
{
var csc = new Controls.CardStackControl
{
MinWidth = MinStackWidth,
Foreground = Foreground,
CardSize = CardSize,
ExactCount = ExactCount,
IsCardsVisible = IsCardsVisible,
Player = Player,
Phase = Phase,
PlayerMode = PlayerMode,
PileVisibility = PileVisibility,
CardCollection = cardStack
};
if (TokenDict != null && TokenDict.ContainsKey(cardStack[0]))
csc.Tokens = TokenDict[cardStack[0]];
if (IsVPsVisible && cardStack[0].HasVPs)
csc.CountVPs(Pile);
else
csc.HideVPs();
if (SplitAt != null && csc.CardCollection.Any() && SplitAt(csc.CardCollection.First()))
currentWrapPanel = wpCardCollections2;
currentWrapPanel.Children.Add(csc);
}
}
InvalidateVisual();
}
public IPlayer Player
{
private get { return _player; }
set
{
_player = value;
foreach (var csc in wpCardCollections.Children.OfType())
csc.Player = value;
}
}
public PhaseEnum Phase
{
private get { return _playerPhase; }
set
{
_playerPhase = value;
foreach (var csc in wpCardCollections.Children.OfType())
csc.Phase = value;
}
}
public PlayerMode PlayerMode
{
private get { return _playerMode; }
set
{
_playerMode = value;
foreach (var csc in wpCardCollections.Children.OfType())
csc.PlayerMode = value;
}
}
private IEnumerable GenerateCardStacks()
{
var cardStacks2 = new OrderedDictionary();
var cardStacks = new List();
if (Pile == null || PileCount == 0)
{
if (DisplayEmptyPile)
cardStacks.Add(new DisplayableCollection() { new DominionBase.Cards.Universal.Blank() });
return cardStacks;
}
int count;
switch (PileVisibility)
{
case DominionBase.Piles.Visibility.All:
IEnumerable copy = new DisplayableCollection(Pile);
if (IsDisplaySorted)
{
copy = copy.OrderBy(c => c.Facing).ThenBy(c => c.Name).ThenByDescending(c => (c as IPoints)?.ComputeVictoryPoints(Player, Pile.OfType()) ?? 0);
}
foreach (var card in copy)
{
var key1 = IsCardsVisible ? ((card.IsStackable && card.Facing == Facing.FaceUp) ? card.Type.ToString() : card.UniqueId.ToString()) : string.Empty;
var vps = IsCardsVisible && card.IsStackable && card is IPoints cp ? cp.ComputeVictoryPoints(Player, Pile.OfType()) : 0;
var key = new Tuple(key1, vps);
if (!cardStacks2.Contains(key))
cardStacks2[key] = new DisplayableCollection();
((DisplayableCollection)cardStacks2[key]).AddRange(card.Stack());
}
cardStacks.AddRange(cardStacks2.Values.OfType());
break;
case DominionBase.Piles.Visibility.Top:
if (PileCount > 0)
{
cardStacks.Add(new DisplayableCollection());
count = PileCount - 1;
if (!ExactCount && count > 1)
{
var variance = Gaussian.NextGaussian();
count += (int)(variance * (count / 4.0));
}
for (var index = 0; index < count; index++)
cardStacks[0].Add(DominionBase.Cards.Universal.Utility.GenerateCardBack(CardBack.Standard));
if (Pile.FirstOrDefault() is Card card)
cardStacks[0].Add(card);
}
break;
case DominionBase.Piles.Visibility.None:
if (PileCount > 0)
{
cardStacks.Add(new DisplayableCollection());
count = PileCount;
if (!ExactCount && count > 1)
{
var variance = Gaussian.NextGaussian();
count += (int)(variance * (count / 4.0));
}
for (var index = 0; index < count; index++)
cardStacks[0].Add(DominionBase.Cards.Universal.Utility.GenerateCardBack(CardBack.Standard));
}
break;
}
return cardStacks;
}
internal Control FindGameObject(IGameObject gameObject)
{
return wpCardCollections.Children.OfType().Select(csc => csc.FindGameObject(gameObject)).FirstOrDefault(fe => fe != null);
}
}
}