/*
   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

// import net.jpountz.lz4
import org.apache.commons.compress.compressors
import java.io.{InputStream => JIS}
import java.io.{OutputStream => JOS}

object Compress{
   implicit val defaultStreamGeneratorLibrary:Set[StreamGenerator] = Set(StreamGenerator.Normal,StreamGenerator.GZ,LZ4,BZ2,DEFLATE,LZMA,PACK200,SNAPPY,XZ,Z,BROTLI)

   def apply(file:File)(implicit sgl:Set[StreamGenerator]=defaultStreamGeneratorLibrary):Option[StreamGenerator] =
       sgl.find(_ canGenerate file)
   // TODO @deprecated("use `find` as more descriptive name here than the magic apply assumption (scala orrientend find?)","v0.2.15")
   // def find(file:File)(implicit sgl:Set[StreamGenerator]=defaultStreamGeneratorLibrary):Option[StreamGenerator] = 

   val GZ = StreamGenerator.GZ
   //TODO @deprecate and rename Normal to Raw
   val Normal = StreamGenerator.Normal
   case object BROTLI extends StreamGenerator{
     val exts:List[String] = List("br","brotli")
     def apply(jis:JIS) = Input(new compressors.brotli.BrotliCompressorInputStream(jis))
     override def canWrite = false
     def apply(jos:JOS) = Output({println("Error: Brotli output streams are not supported");jos})  //apache commons-compress does not contain an outputstream
   }
   case object BZ2 extends StreamGenerator{
     val exts:List[String] = List("bz2")
     def apply(jis:JIS) = Input(new compressors.bzip2.BZip2CompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.bzip2.BZip2CompressorOutputStream(jos))
   }
   case object DEFLATE extends StreamGenerator{
     val exts:List[String] = List("deflate")
     def apply(jis:JIS) = Input(new compressors.deflate.DeflateCompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.deflate.DeflateCompressorOutputStream(jos))
   }
   case object DEFLATE64 extends StreamGenerator{
     val exts:List[String] = List("deflate64")
     def apply(jis:JIS) = Input(new compressors.deflate64.Deflate64CompressorInputStream(jis))
     def apply(jos:JOS) = Output({println("Error: delfate64 output streams are not supported");jos})  //apache commons-compress does not contain an outputstream
     override def canWrite = false
   }
   case object ZST extends StreamGenerator{
     val exts:List[String] = List("zst","zstd")
     def apply(jis:JIS) = Input(new compressors.zstandard.ZstdCompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.zstandard.ZstdCompressorOutputStream(jos))
     //TODO add the ability to parse Framed formats or Block formats for autodetection??
   }
   case object LZ4 extends StreamGenerator{
     val exts:List[String] = List("lz4","lz4-raw")
     //-- "net.jpountz.lz4"    % "lz4"              % "1.3.0",
     def apply(jis:JIS) = Input(new net.jpountz.lz4.LZ4BlockInputStream(jis))
     def apply(jos:JOS) = Output(new net.jpountz.lz4.LZ4BlockOutputStream(jos))
     //TODO add the ability to parse Framed formats or Block formats for autodetection??
   }
   case object LZ4Apache extends StreamGenerator{
     val exts:List[String] = List("lz4-raw-apache")
     def apply(jis:JIS) = Input(new compressors.lz4.FramedLZ4CompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.lz4.FramedLZ4CompressorOutputStream(jos))
     //TODO add the ability to parse Framed formats or Block formats for autodetection??
   }
   case object LZ4Framed extends StreamGenerator{
     val exts:List[String] = List("lz4-framed-apache")
     def apply(jis:JIS) = Input(new compressors.lz4.FramedLZ4CompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.lz4.FramedLZ4CompressorOutputStream(jos))
     //TODO add the ability to parse Framed formats or Block formats for autodetection??
   }
   case object LZMA extends StreamGenerator{
     val exts:List[String] = List("lzma")
     def apply(jis:JIS) = Input(new compressors.lzma.LZMACompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.lzma.LZMACompressorOutputStream(jos))
   }
   case object PACK200 extends StreamGenerator{
     val exts:List[String] = List("pack200","pack")
     def apply(jis:JIS) = Input(new compressors.pack200.Pack200CompressorInputStream(jis))
     override def canWrite = false //FIXME why can't we write to this file format datainputstream readFully is broken???
     def apply(jos:JOS) = Output(new compressors.pack200.Pack200CompressorOutputStream(jos))
   }
   case object SNAPPY extends StreamGenerator{
     val exts:List[String] = List("sz","snappy")
     def apply(jis:JIS) = Input(new compressors.snappy.FramedSnappyCompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.snappy.FramedSnappyCompressorOutputStream(jos))
     //TODO add the ability to parse standard unframmed && Framed format with or Block formats for autodetection??
   }
   case object XZ extends StreamGenerator{
     val exts:List[String] = List("xz")
     def apply(jis:JIS) = Input(new compressors.xz.XZCompressorInputStream(jis))
     def apply(jos:JOS) = Output(new compressors.xz.XZCompressorOutputStream(jos))
   }
   case object Z extends StreamGenerator{
     val exts:List[String] = List("z")
     def apply(jis:JIS) = Input(new compressors.z.ZCompressorInputStream(jis))
     override def canWrite = false
     def apply(jos:JOS) = Output({println("Warning: Z output streams not supported");jos})  //apache commons-compress does not contain an outputstream
   }
}