//--------------------------------------
//               PowerUI
//
//        For documentation or 
//    if you have any issues, visit
//        powerUI.kulestar.com
//
//    Copyright  2013 Kulestar Ltd
//          www.kulestar.com
//--------------------------------------

using System;
using System.Collections;
using System.Collections.Generic;


namespace Css{
	
	/// <summary>
	/// Represents an instance of an textual value.
	/// </summary>
	
	public class ValueSet:CssUnit{
		
		/// <summary>The spacer for this value set.</summary>
		public string Spacer=" ";
		/// <summary>The set of internal values, such as each individual value of padding.</summary>
		internal Value[] Values;
		
		
		public ValueSet(){
			
			// It's a set value by default:
			Type=ValueType.Set;
			
		}
		
		/// <summary>Adds the given value to the set.</summary>
		public void Add(Value val){
			
			if(Values==null){
				Values=new Value[]{val};
				return;
			}
			
			Value[] newSet=new Value[Values.Length+1];
			
			Array.Copy(Values,0,newSet,0,Values.Length);
			
			newSet[Values.Length]=val;
			
			Values=newSet;
			
		}
		
		public ValueSet(int count):this(){
			Count=count;
		}
		
		public ValueSet(Value[] s):this(){
			Values=s;
		}
		
		public override bool IsAbsolute{
			get{
				
				if(Values==null){
					return true;
				}
				
				for(int i=0;i<Values.Length;i++){
					
					Value innerValue=Values[i];
					
					if(innerValue!=null && !innerValue.IsAbsolute){
						return false;
					}
					
				}
				
				return true;
				
			}
		}
		
		public override string Identifier{
			get{
				// Act as the first value in the set:
				Value first=First;
				
				if(first==null){
					return null;
				}
				
				return first.Identifier;
			}
		}
		
		public override void SetRawDecimal(float value){
			// Act as the first value in the set:
			Value first=First;
			
			if(first==null){
				return;
			}
			
			first.SetRawDecimal(value);
		}
		
		public override float GetRawDecimal(){
			// Act as the first value in the set:
			Value first=First;
			
			if(first==null){
				return 0f;
			}
			
			return first.GetRawDecimal();
		}
		
		public override float GetDecimal(RenderableData context,CssProperty property){
			// Act as the first value in the set:
			Value first=First;
			
			if(first==null){
				return 0f;
			}
			
			return first.GetDecimal(context,property);
		}
		
		public override string GetText(RenderableData context,CssProperty property){
			// Act as the first value in the set:
			Value first=First;
			
			if(first==null){
				return null;
			}
			
			return first.GetText(context,property);
		}
		
		public override bool GetBoolean(RenderableData context,CssProperty property){
			// Act as the first value in the set:
			Value first=First;
			
			if(first==null){
				return false;
			}
			
			return first.GetBoolean(context,property);
		}
		
		public Value First{
			get{
				return this[0];
			}
		}
		
		public override int Count{
			get{
				if(Values==null){
					return 0;
				}
				
				return Values.Length;
			}
			set{
				
				if(Values!=null && value==Values.Length){
					// Unchanged.
					return;
				}
				
				// Resizing:
				Value[] newValues=new Value[value];
				
				for(int i=0;i<value;i++){
					// Important to use 'this' here such that it auto wraps:
					newValues[i]=this[i];
				}
				
				Values=newValues;
				
			}
		}
		
		public override string ToString(){
			
			if(Values==null){
				return "";
			}
			
			string result="";
			
			for(int i=0;i<Values.Length;i++){
				
				if(i!=0){
					result+=Spacer;
				}
				
				Value innerValue=Values[i];
				
				if(innerValue==null){
					result+="none";
					continue;
				}
				
				result+=innerValue.ToString();
				
			}
			
			return result;
			
		}
		
		public override IEnumerator<Value> GetEnumerator(){
			
			if(Values!=null){
				
				foreach(Value value in Values){
					
					yield return value;
					
				}
				
			}
			
		}
		
		public override bool Equals(Value value){
			
			if(value==null){
				return false;
			}
			
			ValueSet set=value as ValueSet;
			
			if(set==null){
				return false;
			}
			
			if(set.Count!=Count){
				return false;
			}
			
			for(int i=0;i<Values.Length;i++){
				
				Value valA=Values[i];
				Value valB=set.Values[i];
				
				if(valA==null){
					
					if(valB==null){
						continue;
					}else{
						return false;
					}
					
				}
				
				if(!valA.Equals(valB)){
					return false;
				}
				
			}
			
			return true;
			
		}
		
		public Value[] CopyInnerValues(){
			
			Value[] values=null;
			
			if(Values!=null){
				values=new Value[Values.Length];
				
				for(int i=0;i<Values.Length;i++){
					Value value=Values[i];
					
					if(value==null){
						continue;
					}
					
					values[i]=value.Copy();
				}
				
			}
			
			return values;
		}
		
		protected override Value Clone(){
			ValueSet result=new ValueSet();
			result.Type=Type;
			result.Values=CopyInnerValues();
			return result;
		}
		
		public override bool IsColour{
			get{
				
				int count=Count;
				
				if(count>4){
					return false;
				}
				
				for(int i=0;i<count;i++){
					
					Css.Value v=this[i];
					
					if(v is Css.Keywords.Inherit){
						v=(v as Css.Keywords.Inherit).From;
						
						if(v==null){
							return false;
						}
						
					}	
					
					ValueType type=v.Type;
					
					if(type!=ValueType.Number && type!=ValueType.RelativeNumber){
						return false;
					}
					
				}
				
				return true;
		
			}
		}
		
		public override Value this[int index]{
			get{
				
				if(Values==null || Values.Length==0){
					return Value.Empty;
				}
				
				// Auto wrap.
				// This drives e.g. border-width:2px 2px (where the other 2 widths are inferred via wrapping).
				// Note that border-width:2px is dealt with differently; it's not actually a set at all.
				if(index>=Values.Length){
					index=index%Values.Length;
				}
				
				Value value=Values[index];
				
				if(value==null){
					return Value.Empty;
				}
				
				return value;
			}
			set{
				if(Values==null){
					Values=new Value[index+1];
				}else if(index>=Values.Length){
					Count=index+1;
				}
				
				Values[index]=value;
			}
		}
		
	}
	
}



