/*
   Copyright 2010 Aaron J. Radke

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
package cc.drx

object Style{

   //#---Properties
   sealed trait Property{
      /**composing two Style properties creates a Style*/
      def ~(that:Property):Style = Style(Set(this,that))
   }

   case object Default extends Property

   case class Background(c:Color) extends Property

   trait ColorOption{
     def colorOption:Option[Color]
   }
   sealed trait FillOption extends Property with ColorOption
   case object FillNone extends FillOption{
     def colorOption:Option[Color] = None
   }
   case class Fill(c:Color) extends FillOption{
     def colorOption:Option[Color] = Some(c)
   }
   //Strokes
   sealed trait StrokeOption extends Property with ColorOption
   case object StrokeNone extends StrokeOption{
     def colorOption:Option[Color] = None
   }
   case class Stroke(c:Color) extends StrokeOption{
     /**convenience function for composition*/
     def weight(w:Double) = this ~ Weight(w)
     def colorOption:Option[Color] = Some(c)
   }
   case class Weight(value:Double) extends Property

   //##---Property -> Font
   object Font{
      def apply(size:Double):Font = Font("Helvetica",size)
      def apply(name:String):Font = Font(name,12)
      // def list(g:DrawContext):List[Font] = g.listFonts //TODO 
   }
   case class Font(name:String,size:Double) extends Property

   //##---Property -> Alignment
   sealed trait AlignHorizontal extends Property
   case object Left extends AlignHorizontal
   case object Right extends AlignHorizontal
   case object Center extends AlignHorizontal

   sealed trait AlignVertical extends Property
   case object Top extends AlignVertical
   case object Bottom extends AlignVertical
   case object Midline extends AlignVertical //Vertical Center

   case class Align(horz:AlignHorizontal, vert:AlignVertical) extends Property

   //##---Property -> Transformation
   case class Translate(t:Vec) extends Property
   case class ScaleProperty(t:Vec) extends Property
   case class Rotate(r:Angle) extends Property
   case class Transform(translate:Vec=Vec(0,0),rotate:Angle=Angle(0),scale:Vec=Vec(1,1)) extends Property
   object Transform{
     def apply(translate:Vec,rotate:Angle,scale:Double):Transform = new Transform(translate, rotate, Vec(scale,scale))
     def apply(translate:Vec,scale:Double):Transform = new Transform(translate, Angle(0), Vec(scale,scale))
     def apply(a:Rect, b:Rect):Transform = {
       val s = b.width/a.width //TODO add hight scale as well
       val d = a.a - b.a
       Transform(translate = d, scale = Vec(s,s))
     }
   }

   implicit class DrxStyleString(val string:String) extends AnyVal{
     //TODO 2017-07-30("use Text(string,v) instead it is hard to see what is going on and search","v.0.2.15??")
     def ~(v:Vec):Text = Text(string,v) //TODO this feels very hacky because Text is not a style but often used in a similar manner
   }
}
/**A style is a set of style properties*/
case class Style(properties:Set[Style.Property]=Set()) extends Iterable[Style.Property]{
   // def foreach[U](f: Style.Property => U):Unit = properties foreach f  //Implements Traversable prior to 2.13
   def iterator:Iterator[Style.Property] = properties.iterator

   /**add a style property to the set (clobber if one already exists*/
   def ~(additionalProperty:Style.Property):Style = Style(properties + additionalProperty)
   /**merge a Style  (clobber if some properties already exist)*/
   def ~(mergeStyle:Style):Style = Style(properties ++ mergeStyle.properties)
}