package scala.collection
package mutable
import scala.reflect.ClassManifest
import scala.collection.generic._
import scala.collection.parallel.mutable.ParArray
abstract class WrappedArray[T]
extends IndexedSeq[T]
    with ArrayLike[T, WrappedArray[T]]
    with CustomParallelizable[T, ParArray[T]]
{
  override protected[this] def thisCollection: WrappedArray[T] = this
  override protected[this] def toCollection(repr: WrappedArray[T]): WrappedArray[T] = repr
  
  def elemManifest: ClassManifest[T]
  
  def length: Int
  
  def apply(index: Int): T
  
  def update(index: Int, elem: T): Unit
  
  def array: Array[T]
  
  override def par = ParArray.handoff(array)
  
  override def toArray[U >: T : ClassManifest]: Array[U] =
    if (implicitly[ClassManifest[U]].erasure eq array.getClass.getComponentType)
      array.asInstanceOf[Array[U]]
    else 
      super.toArray[U]
  
  override def stringPrefix = "WrappedArray"
  
  
  override def clone: WrappedArray[T] = WrappedArray make array.clone()
 
  
  override protected[this] def newBuilder: Builder[T, WrappedArray[T]] = 
    new WrappedArrayBuilder[T](elemManifest)
  
}
object WrappedArray {
  
  private val EmptyWrappedArray  = new ofRef[AnyRef](new Array[AnyRef](0))
  def empty[T <: AnyRef]: WrappedArray[T] = EmptyWrappedArray.asInstanceOf[WrappedArray[T]]
  
  
  
  
  
  
  def make[T](x: AnyRef): WrappedArray[T] = (x match {
    case null              => null
    case x: Array[AnyRef]  => new ofRef[AnyRef](x)
    case x: Array[Int]     => new ofInt(x)
    case x: Array[Double]  => new ofDouble(x)
    case x: Array[Long]    => new ofLong(x)
    case x: Array[Float]   => new ofFloat(x)
    case x: Array[Char]    => new ofChar(x)
    case x: Array[Byte]    => new ofByte(x)
    case x: Array[Short]   => new ofShort(x)
    case x: Array[Boolean] => new ofBoolean(x)
    case x: Array[Unit]    => new ofUnit(x)
  }).asInstanceOf[WrappedArray[T]]
  implicit def canBuildFrom[T](implicit m: ClassManifest[T]): CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] =
    new CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] {
      def apply(from: WrappedArray[_]): Builder[T, WrappedArray[T]] =
        ArrayBuilder.make[T]()(m) mapResult WrappedArray.make[T]
      def apply: Builder[T, WrappedArray[T]] =
        ArrayBuilder.make[T]()(m) mapResult WrappedArray.make[T]
  }
    
  def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer
  final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable {
    lazy val elemManifest = ClassManifest.classType[T](array.getClass.getComponentType)
    def length: Int = array.length
    def apply(index: Int): T = array(index).asInstanceOf[T]
    def update(index: Int, elem: T) { array(index) = elem }
  }
  final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable {
    def elemManifest = ClassManifest.Byte
    def length: Int = array.length
    def apply(index: Int): Byte = array(index)
    def update(index: Int, elem: Byte) { array(index) = elem }
  }
  final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable {
    def elemManifest = ClassManifest.Short
    def length: Int = array.length
    def apply(index: Int): Short = array(index)
    def update(index: Int, elem: Short) { array(index) = elem }
  }
  final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable {
    def elemManifest = ClassManifest.Char
    def length: Int = array.length
    def apply(index: Int): Char = array(index)
    def update(index: Int, elem: Char) { array(index) = elem }
  }
  final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable {
    def elemManifest = ClassManifest.Int
    def length: Int = array.length
    def apply(index: Int): Int = array(index)
    def update(index: Int, elem: Int) { array(index) = elem }
  }
  final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable {
    def elemManifest = ClassManifest.Long
    def length: Int = array.length
    def apply(index: Int): Long = array(index)
    def update(index: Int, elem: Long) { array(index) = elem }
  }
  final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable {
    def elemManifest = ClassManifest.Float
    def length: Int = array.length
    def apply(index: Int): Float = array(index)
    def update(index: Int, elem: Float) { array(index) = elem }
  }
  final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable {
    def elemManifest = ClassManifest.Double
    def length: Int = array.length
    def apply(index: Int): Double = array(index)
    def update(index: Int, elem: Double) { array(index) = elem }
  }
  final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable {
    def elemManifest = ClassManifest.Boolean
    def length: Int = array.length
    def apply(index: Int): Boolean = array(index)
    def update(index: Int, elem: Boolean) { array(index) = elem }
  }
  final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable {
    def elemManifest = ClassManifest.Unit
    def length: Int = array.length
    def apply(index: Int): Unit = array(index)
    def update(index: Int, elem: Unit) { array(index) = elem }
  }
}