import Element.elem
abstract class Element{
  def contents: Array[String]

  def height: Int = contents.length
  def width: Int = contents(0).length

  

  def above(that: Element): Element = {
    //new ArrayElement(this.contents ++ that.contents)
    val this1 = this widen that.width
    val that1 = that widen this.width
    elem(this1.contents ++ that1.contents)
  }
  def left_align(that: Element): Element = {
    if (this.width == that.width){
      this above that
    }
    else if (this.width < that.width) {
      (this beside elem(' ', that.width - this.width, this.height)) above that
    }
    else {
      this above (that beside elem(' ', this.width - that.width, that.height))
    }
  }
  def up_align(that: Element): Element = {
    if (this.height == that.height){
      this beside that
    }
    else if (this.height < that.height) {
      (this above elem(' ', this.width, that.height - this.height)) beside that
    }
    else {
      this beside (that above elem(' ', that.width, this.height - that.height))
    }  
  }
  def beside(that: Element): Element = {
    val this1 = this heighten that.height
    val that1 = that heighten this.height
    elem(
      for ((line1, line2) <- this1.contents zip that1.contents)
      yield line1 + line2)
  }
  def widen(w: Int): Element = 
    if(w <= width) this
    else {
      val left = Element.elem(' ', (w - width) / 2, height)
      var right = Element.elem(' ', w - width - left.width, height)
      left beside this beside right
    }
  def heighten(h: Int): Element = 
    if (h <= height) this
    else {
      val top = Element.elem(' ', width, (h - height) / 2)
      val bot = Element.elem(' ', width, h - height - top.height)
      top above this above bot
    }
  override def toString = contents mkString "\n"
}
object Element {
  private class ArrayElement(
    val contents: Array[String]
  ) extends Element

  private class LineElement(s: String) extends Element {
    val contents = Array(s)
    override def width = s.length
    override def height = 1
  }

  private class UniformElement(
    ch: Char,
    override val width: Int,
    override val height: Int
  ) extends Element {
    private val line = ch.toString * width
    def contents = Array.fill(height)(line)
  }

  def elem(contents: Array[String]): Element =
    new ArrayElement(contents)
    
  def elem(chr: Char, width: Int, height: Int): Element =
    new UniformElement(chr, width, height)
    
  def elem(line: String): Element =
      new LineElement(line)
}