/*
 * Copyright (C) 2016 Square, Inc.
 *
 * 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 okio

import java.io.IOException
import java.security.InvalidKeyException
import java.security.MessageDigest
import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec

/**
 * A sink that computes a hash of the full stream of bytes it has accepted. To use, create an
 * instance with your preferred hash algorithm. Write all of the data to the sink and then call
 * [hash] to compute the final hash value.
 *
 * In this example we use `HashingSink` with a [BufferedSink] to make writing to the
 * sink easier.
 * ```
 * HashingSink hashingSink = HashingSink.sha256(s);
 * BufferedSink bufferedSink = Okio.buffer(hashingSink);
 *
 * ... // Write to bufferedSink and either flush or close it.
 *
 * ByteString hash = hashingSink.hash();
 * ```
 */
actual class HashingSink : ForwardingSink, Sink { // Need to explicitly declare sink pending fix for https://youtrack.jetbrains.com/issue/KT-20641
  private val messageDigest: MessageDigest?
  private val mac: Mac?

  internal constructor(sink: Sink, digest: MessageDigest) : super(sink) {
    this.messageDigest = digest
    this.mac = null
  }

  internal constructor(sink: Sink, algorithm: String) : this(sink, MessageDigest.getInstance(algorithm))

  internal constructor(sink: Sink, mac: Mac) : super(sink) {
    this.mac = mac
    this.messageDigest = null
  }

  internal constructor(sink: Sink, key: ByteString, algorithm: String) : this(
    sink,
    try {
      Mac.getInstance(algorithm).apply {
        init(SecretKeySpec(key.toByteArray(), algorithm))
      }
    } catch (e: InvalidKeyException) {
      throw IllegalArgumentException(e)
    }
  )

  @Throws(IOException::class)
  override fun write(source: Buffer, byteCount: Long) {
    checkOffsetAndCount(source.size, 0, byteCount)

    // Hash byteCount bytes from the prefix of source.
    var hashedCount = 0L
    var s = source.head!!
    while (hashedCount < byteCount) {
      val toHash = minOf(byteCount - hashedCount, s.limit - s.pos).toInt()
      if (messageDigest != null) {
        messageDigest.update(s.data, s.pos, toHash)
      } else {
        mac!!.update(s.data, s.pos, toHash)
      }
      hashedCount += toHash
      s = s.next!!
    }

    // Write those bytes to the sink.
    super.write(source, byteCount)
  }

  /**
   * Returns the hash of the bytes accepted thus far and resets the internal state of this sink.
   *
   * **Warning:** This method is not idempotent. Each time this method is called its
   * internal state is cleared. This starts a new hash with zero bytes accepted.
   */
  @get:JvmName("hash")
  actual val hash: ByteString
    get() {
      val result = if (messageDigest != null) messageDigest.digest() else mac!!.doFinal()
      return ByteString(result)
    }

  @JvmName("-deprecated_hash")
  @Deprecated(
    message = "moved to val",
    replaceWith = ReplaceWith(expression = "hash"),
    level = DeprecationLevel.ERROR
  )
  fun hash() = hash

  actual companion object {
    /** Returns a sink that uses the obsolete MD5 hash algorithm to produce 128-bit hashes. */
    @JvmStatic
    actual fun md5(sink: Sink) = HashingSink(sink, "MD5")

    /** Returns a sink that uses the obsolete SHA-1 hash algorithm to produce 160-bit hashes. */
    @JvmStatic
    actual fun sha1(sink: Sink) = HashingSink(sink, "SHA-1")

    /** Returns a sink that uses the SHA-256 hash algorithm to produce 256-bit hashes. */
    @JvmStatic
    actual fun sha256(sink: Sink) = HashingSink(sink, "SHA-256")

    /** Returns a sink that uses the SHA-512 hash algorithm to produce 512-bit hashes. */
    @JvmStatic
    actual fun sha512(sink: Sink) = HashingSink(sink, "SHA-512")

    /** Returns a sink that uses the obsolete SHA-1 HMAC algorithm to produce 160-bit hashes. */
    @JvmStatic
    actual fun hmacSha1(sink: Sink, key: ByteString) = HashingSink(sink, key, "HmacSHA1")

    /** Returns a sink that uses the SHA-256 HMAC algorithm to produce 256-bit hashes. */
    @JvmStatic
    actual fun hmacSha256(sink: Sink, key: ByteString) = HashingSink(sink, key, "HmacSHA256")

    /** Returns a sink that uses the SHA-512 HMAC algorithm to produce 512-bit hashes. */
    @JvmStatic
    actual fun hmacSha512(sink: Sink, key: ByteString) = HashingSink(sink, key, "HmacSHA512")
  }
}
