using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using LeanCloud.Utilities; namespace LeanCloud.Storage.Internal { public class AVAddUniqueOperation : IAVFieldOperation { private ReadOnlyCollection objects; public AVAddUniqueOperation(IEnumerable objects) { this.objects = new ReadOnlyCollection(objects.Distinct().ToList()); } public object Encode() { return new Dictionary { {"__op", "AddUnique"}, {"objects", PointerOrLocalIdEncoder.Instance.Encode(objects)} }; } public IAVFieldOperation MergeWithPrevious(IAVFieldOperation previous) { if (previous == null) { return this; } if (previous is AVDeleteOperation) { return new AVSetOperation(objects.ToList()); } if (previous is AVSetOperation) { var setOp = (AVSetOperation)previous; var oldList = Conversion.To>(setOp.Value); var result = this.Apply(oldList, null); return new AVSetOperation(result); } if (previous is AVAddUniqueOperation) { var oldList = ((AVAddUniqueOperation)previous).Objects; return new AVAddUniqueOperation((IList)this.Apply(oldList, null)); } throw new InvalidOperationException("Operation is invalid after previous operation."); } public object Apply(object oldValue, string key) { if (oldValue == null) { return objects.ToList(); } var newList = Conversion.To>(oldValue).ToList(); var comparer = AVFieldOperations.AVObjectComparer; foreach (var objToAdd in objects) { if (objToAdd is AVObject) { var matchedObj = newList.FirstOrDefault(listObj => comparer.Equals(objToAdd, listObj)); if (matchedObj == null) { newList.Add(objToAdd); } else { var index = newList.IndexOf(matchedObj); newList[index] = objToAdd; } } else if (!newList.Contains(objToAdd, comparer)) { newList.Add(objToAdd); } } return newList; } public IEnumerable Objects { get { return objects; } } } }