/*
 * Copyright (C) 2019 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.
 */

// TODO move to SegmentedByteString class: https://youtrack.jetbrains.com/issue/KT-20427
@file:Suppress("NOTHING_TO_INLINE")

package okio.internal

import okio.Buffer
import okio.ByteString
import okio.Segment
import okio.SegmentedByteString
import okio.arrayRangeEquals
import okio.checkOffsetAndCount

internal fun IntArray.binarySearch(value: Int, fromIndex: Int, toIndex: Int): Int {
  var left = fromIndex
  var right = toIndex - 1

  while (left <= right) {
    val mid = (left + right) ushr 1 // protect from overflow
    val midVal = this[mid]

    when {
      midVal < value -> left = mid + 1
      midVal > value -> right = mid - 1
      else -> return mid
    }
  }

  // no exact match, return negative of where it should match
  return -left - 1
}

/** Returns the index of the segment that contains the byte at `pos`.  */
internal fun SegmentedByteString.segment(pos: Int): Int {
  // Search for (pos + 1) instead of (pos) because the directory holds sizes, not indexes.
  val i = directory.binarySearch(pos + 1, 0, segments.size)
  return if (i >= 0) i else i.inv() // If i is negative, bitflip to get the insert position.
}

/** Processes all segments, invoking `action` with the ByteArray and range of valid data. */
internal inline fun SegmentedByteString.forEachSegment(
  action: (data: ByteArray, offset: Int, byteCount: Int) -> Unit
) {
  val segmentCount = segments.size
  var s = 0
  var pos = 0
  while (s < segmentCount) {
    val segmentPos = directory[segmentCount + s]
    val nextSegmentOffset = directory[s]

    action(segments[s], segmentPos, nextSegmentOffset - pos)
    pos = nextSegmentOffset
    s++
  }
}

/**
 * Processes the segments between `beginIndex` and `endIndex`, invoking `action` with the ByteArray
 * and range of the valid data.
 */
private inline fun SegmentedByteString.forEachSegment(
  beginIndex: Int,
  endIndex: Int,
  action: (data: ByteArray, offset: Int, byteCount: Int) -> Unit
) {
  var s = segment(beginIndex)
  var pos = beginIndex
  while (pos < endIndex) {
    val segmentOffset = if (s == 0) 0 else directory[s - 1]
    val segmentSize = directory[s] - segmentOffset
    val segmentPos = directory[segments.size + s]

    val byteCount = minOf(endIndex, segmentOffset + segmentSize) - pos
    val offset = segmentPos + (pos - segmentOffset)
    action(segments[s], offset, byteCount)
    pos += byteCount
    s++
  }
}

// TODO Kotlin's expect classes can't have default implementations, so platform implementations
// have to call these functions. Remove all this nonsense when expect class allow actual code.

internal inline fun SegmentedByteString.commonSubstring(beginIndex: Int, endIndex: Int): ByteString {
  require(beginIndex >= 0) { "beginIndex=$beginIndex < 0" }
  require(endIndex <= size) { "endIndex=$endIndex > length($size)" }

  val subLen = endIndex - beginIndex
  require(subLen >= 0) { "endIndex=$endIndex < beginIndex=$beginIndex" }

  when {
    beginIndex == 0 && endIndex == size -> return this
    beginIndex == endIndex -> return ByteString.EMPTY
  }

  val beginSegment = segment(beginIndex) // First segment to include
  val endSegment = segment(endIndex - 1) // Last segment to include

  val newSegments = segments.copyOfRange(beginSegment, endSegment + 1)
  val newDirectory = IntArray(newSegments.size * 2)
  var index = 0
  for (s in beginSegment..endSegment) {
    newDirectory[index] = minOf(directory[s] - beginIndex, subLen)
    newDirectory[index++ + newSegments.size] = directory[s + segments.size]
  }

  // Set the new position of the first segment
  val segmentOffset = if (beginSegment == 0) 0 else directory[beginSegment - 1]
  newDirectory[newSegments.size] += beginIndex - segmentOffset

  return SegmentedByteString(newSegments, newDirectory)
}

internal inline fun SegmentedByteString.commonInternalGet(pos: Int): Byte {
  checkOffsetAndCount(directory[segments.size - 1].toLong(), pos.toLong(), 1)
  val segment = segment(pos)
  val segmentOffset = if (segment == 0) 0 else directory[segment - 1]
  val segmentPos = directory[segment + segments.size]
  return segments[segment][pos - segmentOffset + segmentPos]
}

internal inline fun SegmentedByteString.commonGetSize() = directory[segments.size - 1]

internal inline fun SegmentedByteString.commonToByteArray(): ByteArray {
  val result = ByteArray(size)
  var resultPos = 0
  forEachSegment { data, offset, byteCount ->
    data.copyInto(
      result, destinationOffset = resultPos, startIndex = offset,
      endIndex = offset + byteCount
    )
    resultPos += byteCount
  }
  return result
}

internal inline fun SegmentedByteString.commonWrite(buffer: Buffer, offset: Int, byteCount: Int) {
  forEachSegment(offset, offset + byteCount) { data, offset, byteCount ->
    val segment = Segment(data, offset, offset + byteCount, true, false)
    if (buffer.head == null) {
      segment.prev = segment
      segment.next = segment.prev
      buffer.head = segment.next
    } else {
      buffer.head!!.prev!!.push(segment)
    }
  }
  buffer.size += byteCount
}

internal inline fun SegmentedByteString.commonRangeEquals(
  offset: Int,
  other: ByteString,
  otherOffset: Int,
  byteCount: Int
): Boolean {
  if (offset < 0 || offset > size - byteCount) return false
  // Go segment-by-segment through this, passing arrays to other's rangeEquals().
  var otherOffset = otherOffset
  forEachSegment(offset, offset + byteCount) { data, offset, byteCount ->
    if (!other.rangeEquals(otherOffset, data, offset, byteCount)) return false
    otherOffset += byteCount
  }
  return true
}

internal inline fun SegmentedByteString.commonRangeEquals(
  offset: Int,
  other: ByteArray,
  otherOffset: Int,
  byteCount: Int
): Boolean {
  if (offset < 0 || offset > size - byteCount ||
    otherOffset < 0 || otherOffset > other.size - byteCount
  ) {
    return false
  }
  // Go segment-by-segment through this, comparing ranges of arrays.
  var otherOffset = otherOffset
  forEachSegment(offset, offset + byteCount) { data, offset, byteCount ->
    if (!arrayRangeEquals(data, offset, other, otherOffset, byteCount)) return false
    otherOffset += byteCount
  }
  return true
}

internal inline fun SegmentedByteString.commonEquals(other: Any?): Boolean {
  return when {
    other === this -> true
    other is ByteString -> other.size == size && rangeEquals(0, other, 0, size)
    else -> false
  }
}

internal inline fun SegmentedByteString.commonHashCode(): Int {
  var result = hashCode
  if (result != 0) return result

  // Equivalent to Arrays.hashCode(toByteArray()).
  result = 1
  forEachSegment { data, offset, byteCount ->
    var i = offset
    val limit = offset + byteCount
    while (i < limit) {
      result = 31 * result + data[i]
      i++
    }
  }
  hashCode = result
  return result
}
