from typing import Sequence
from typing import Union
from typing import List
from typing import Dict


def get_read_instructions(from_: int,
                          to: int,
                          filenames: Sequence[Union[str, int]],
                          shard_lengths: Sequence[int],
                          shardref_name: str = "filename") -> List[Dict]:
  """Returns a list of files (+skip/take) to read [from_:to] items from shards.

  Args:
    from_: int, Index (included) of element from which to read.
    to: int, Index (excluded) of element to which to read.
    filenames: list of strings or ints, the filenames of the shards. Not really
      used, but to place in result.
    shard_lengths: the number of elements in every shard.
    shardref_name: string, defaults to "filename". How to name the field holding
      the shard-reference in result dict.

  Returns:
    list of dict(filename, skip, take).
  """
  index_start = 0 # Beginning (included) of moving window.
  index_end = 0 # End (excluded) of moving window.
  files = []
  for filename, length in zip(filenames, shard_lengths):
    if not length:
      continue # Empty shard - can happen with temporary buckets.
    index_end += length
    if from_ < index_end and to > index_start: # There is something to take.
      skip = from_ - index_start if from_ > index_start else 0
      take = to - index_start - skip if to < index_end else -1
      if take == 0:
        continue
      files.append({shardref_name: filename, "skip": skip, "take": take})
    index_start += length
  return files