/* ICookieJar ADT Interface, Immutable Method-Chaining Functions
   Using Scala Immutable Data Structures, Blackbox test objects
   CSci 555: Functional Programming, Spring 2016
   H. Conrad Cunningham, Professor
   Computer and Information Science
   University of Mississippi

1234567890123456789012345678901234567890123456789012345678901234567890

2016-03-09: Developed immutable Scala versions from 2010-12
            mutable Scala versions
2022-04-18: Scala 3 compatibility check, minor changes to comments
            and to procedure def's and calls

See the comments in ICookieJar.scala and ICookieJarList.scala for more
information on this family of ADTs.

*/

/* Object CookieJarTest's main method runs a simple blackbox testing
   script for the various concrete CookieJar classes.  

*/

import scala.collection.immutable.HashMap

object ICookieJarTest {

  // Main method for testing
  def main(args: Array[String]): Unit = {

    println("\nBegin CookieJar test.")

    // Test ICookieJarList, the List-based ICookieJar class
    println("\nBegin ICookieJarList test.\n")
    val j0: ICookieJar[String] = new ICookieJarList[String](Nil)
    println(
      "val j0: ICookieJar[String] = new ICookieJarList[String](Nil)" )
    testCookieJar(j0)
    println("End ICookieJarList test.")

    // Test CookJarMap, the Map-based CookieJar class
    println("\nBegin ICookieJarMap test.\n")
    val j1 = new ICookieJarMap[String](new HashMap[String,Int]())
    println("j1 = new ICookieJarMap[String]" )
    testCookieJar(j1)
    println("End CookieJarMap test.")

    // Test ICookJarTupleList, the Tuple-List-based CookieJar class
    println("\nBegin ICookieJarTupleList test.\n")
    val j2 = new ICookieJarTupleList[String](Nil:List[(String,Int)])
    println("j2 = new ICookieJarTupleList[String]" )
    testCookieJar(j2)
    println("End CookieJarTupleList test.")

    println("\nEnd CookieJar test.\n")
  }
   
  // A script for blackbox testing of any CookieJar[String]
  private def testCookieJar(j: ICookieJar[String]): Unit =  {
    println(  "j                        = " + j)
    println(  "j.isEmpty                = " + j.isEmpty)    
    println("j.has(\"Cookie1\")         = " + j.has("Cookie1"))
    println("j.has(\"Cookie2\")         = " + j.has("Cookie2"))
    println()

    val j2 = j.putIn("Cookie1")
    println("j2 = j.putIn(\"Cookie1\")  = " + j2)
    println(  "j2.isEmpty               = " + j2.isEmpty)
    println("j2.has(\"Cookie1\")        = " + j2.has("Cookie1"))
    println("j2.has(\"Cookie2\")        = " + j2.has("Cookie2"))
    println()

    val j3 = j2.putIn("Cookie2")
    println("j3 = j2.putIn(\"Cookie2\")  = " + j3)
    println(  "j3.isEmpty                = " + j3.isEmpty)
    println("j3.has(\"Cookie1\")         = " + j3.has("Cookie1"))
    println("j3.has(\"Cookie2\")         = " + j3.has("Cookie2"))
    println()

    val j4 = j3.putIn("Cookie1")
    println("j4 = j3.putIn(\"Cookie1\")  = " + j4)
    println(  "j4.isEmpty                = " + j4.isEmpty)
    println("j4.has(\"Cookie1\")         = " + j4.has("Cookie1"))
    println("j4.has(\"Cookie2\")         = " + j4.has("Cookie2"))
    println()

    val j5 = j4.eat("Cookie1")
    println("j5 = j4.eat(\"Cookie1\")    = " + j5)
    println(  "j5.isEmpty                = " + j5.isEmpty)
    println("j5.has(\"Cookie1\")         = " + j5.has("Cookie1"))
    println("j5.has(\"Cookie2\")         = " + j5.has("Cookie2"))
    println()

    val j6 = j5.eat("Cookie1")
    println("j6 = j5.eat(\"Cookie1\")    = " + j6)
    println(  "j6.isEmpty                = " + j6.isEmpty)
    println("j6.has(\"Cookie1\")         = " + j6.has("Cookie1"))
    println("j6.has(\"Cookie2\")         = " + j6.has("Cookie2"))
    println()

    val j7 = j6.eat("Cookie2")
    println("j7 = j6.eat(\"Cookie2\")    = " + j6)
    println(  "j7.isEmpty                = " + j7.isEmpty)
    println("j7.has(\"Cookie1\")         = " + j7.has("Cookie1"))
    println("j7.has(\"Cookie2\")         = " + j7.has("Cookie2"))
    println()

    print("j8 = j7.eat(\"Cookie2\")        " )
    try   { val j8 = j7.eat("Cookie2"); println(j8) }
    catch { case ex: Throwable => println("\nERROR " + ex) 
    }
    println()

  }
}

