""" This file contains the python code for Freeman chain coding
Based on : http://www.cs.unca.edu/~reiser/imaging/chaincode.html

     Given a binary image of dimension n x m, with a background pixel intensity of 0 and foreground intensity of 1.
     Assume there is one object of interest in the image (otherwise take steps to remove the other objects).

/* Directions  0 1 2    Change in    -1  0  1   Change in    -1 -1 -1
               7 x 3    x-dimension  -1  0  1   y-dimension   0  0  0
               6 5 4                 -1  0  1                 1  1  1
 Marjorie Roscian, 2018 """

# import cv2
import numpy as np


def FreemanChainCode(img):
    # Find the first pixel on the boundary of the object

    # img = cv2.imread('picture_75.tif', 0)
    rows, cols = img.shape
    for r in np.arange(0, rows):
        for c in np.arange(0, cols):
            if img[r, c] == 255:
                start_point = (r, c)
                print(start_point, img[r, c])
                break
        else:
            continue
        break

    # Write chain code
    directions = [0, 1, 2,
                  7, 3,
                  6, 5, 4]
    dir2idx = dict(zip(directions, range(len(directions))))

    change_j = [-1, 0, 1,  # x or columns
                -1, 1,
                -1, 0, 1]

    change_i = [-1, -1, -1,  # y or rows
                0, 0,
                1, 1, 1]

    border = []
    chain = []
    curr_point = start_point
    for direction in directions:
        idx = dir2idx[direction]
        new_point = (start_point[0] + change_i[idx], start_point[1] + change_j[idx])
        if img[new_point] != 0:  # if is ROI
            border.append(new_point)
            chain.append(direction)
            curr_point = new_point
            break

    count = 0
    while curr_point != start_point:
        # figure direction to start search
        b_direction = (direction + 5) % 8
        dirs_1 = range(b_direction, 8)
        dirs_2 = range(0, b_direction)
        dirs = []
        dirs.extend(dirs_1)
        dirs.extend(dirs_2)
        for direction in dirs:
            idx = dir2idx[direction]
            new_point = (curr_point[0] + change_i[idx], curr_point[1] + change_j[idx])
            if img[new_point] != 0:  # if is ROI
                border.append(new_point)
                chain.append(direction)
                curr_point = new_point
                break
        if count == 1000:
            break
        count += 1

    print("DONE")
    # print(border)

    # Printing result

    # plt.imshow(img, cmap='Greys')
    # plt.plot([i[1] for i in border], [i[0] for i in border])

    return border
