#-------------------------------------------------------------
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.
#
#-------------------------------------------------------------

# The img_crop_linearized cuts out a rectangular section of multiple linearized images.
#
# .. code-block:: python
#
#   >>> import numpy as np
#   >>> from systemds.context import SystemDSContext
#   >>> from systemds.operator.algorithm import img_crop_linearized
#   >>> 
#   >>> with SystemDSContext() as sds:
#   ...     img = sds.from_numpy(
#   ...         np.array([[ 50., 100., 150.,
#   ...                     150., 200., 250.,
#   ...                     250., 200., 200. ]], dtype=np.float32)
#   ...     )
#   ...     result_img = img_crop_linearized(img, 1, 1, 1, 1, 3, 3).compute()
#   ...     print(result_img)
#   [[200.]]
#
#
# INPUT:
# ----------------------------------------------------------------------------------------
# img_in     Input images as linearized 2D matrix with top left corner at [1, 1] (every row represents a linearized matrix/image)
# w          The width of the subregion required
# h          The height of the subregion required
# x_offset   The horizontal offset for the center of the crop region
# y_offset   The vertical offset for the center of the crop region
# s_cols     Width of a single image
# s_rows     Height of a single image
# ----------------------------------------------------------------------------------------
#
# OUTPUT:
# --------------------------------------------------------------------------------------------------
# img_out     Cropped images as linearized 2D matrix
# --------------------------------------------------------------------------------------------------

m_img_crop_linearized = function(Matrix[Double] img_in, Integer w, Integer h, Integer x_offset, Integer y_offset, 
  Integer s_cols, Integer s_rows) return (Matrix[Double] img_out) {
  
  orig_w = s_cols
  orig_h = s_rows

  nrows = nrow(img_in) # number of images

  start_h = (ceil((orig_h - h) / 2)) + y_offset
  end_h = (start_h + h - 1) 
  start_w = (ceil((orig_w - w) / 2)) + x_offset
  end_w = (start_w + w - 1) 

  if((start_h < 0) | (end_h > orig_h) | (start_w < 0) | (end_w > orig_w)) {
    print("Offset out of bounds! Returning input.")
    img_out = img_in
  }
  else {
    mask = matrix(0, rows=orig_h, cols=orig_w)
    temp_mask = matrix(1, rows=h , cols=w )
    mask[start_h:end_h, start_w:end_w] = temp_mask

    linear_mask = matrix(mask, rows=1, cols=orig_w * orig_h)

    img_out = matrix(removeEmpty(target=(matrix(img_in+1, nrow(img_in), ncol(img_in))), margin="cols", select=linear_mask) - 1, nrows, w * h)
  }
}

