import numpy as np
from scipy.ndimage.filters import gaussian_filter

from ..util import img_as_float
from .util import _mask_border_keypoints, pairwise_hamming_distance

from ._brief_cy import _brief_loop


def brief(image, keypoints, descriptor_size=256, mode='normal', patch_size=49,
          sample_seed=1, variance=2):
    """**Experimental function**.

    Extract BRIEF Descriptor about given keypoints for a given image.

    Parameters
    ----------
    image : 2D ndarray
        Input image.
    keypoints : (P, 2) ndarray
        Array of keypoint locations in the format (row, col).
    descriptor_size : int
        Size of BRIEF descriptor about each keypoint. Sizes 128, 256 and 512
        preferred by the authors. Default is 256.
    mode : string
        Probability distribution for sampling location of decision pixel-pairs
        around keypoints. Default is 'normal' otherwise uniform.
    patch_size : int
        Length of the two dimensional square patch sampling region around
        the keypoints. Default is 49.
    sample_seed : int
        Seed for sampling the decision pixel-pairs. From a square window with
        length patch_size, pixel pairs are sampled using the `mode` parameter
        to build the descriptors using intensity comparison. The value of
        `sample_seed` should be the same for the images to be matched while
        building the descriptors. Default is 1.
    variance : float
        Variance of the Gaussian Low Pass filter applied on the image to
        alleviate noise sensitivity. Default is 2.

    Returns
    -------
    descriptors : (Q, `descriptor_size`) ndarray of dtype bool
        2D ndarray of binary descriptors of size `descriptor_size` about Q
        keypoints after filtering out border keypoints with value at an index
        (i, j) either being True or False representing the outcome
        of Intensity comparison about ith keypoint on jth decision pixel-pair.
    keypoints : (Q, 2) ndarray
        Location i.e. (row, col) of keypoints after removing out those that
        are near border.

    References
    ----------
    .. [1] Michael Calonder, Vincent Lepetit, Christoph Strecha and Pascal Fua
           "BRIEF : Binary robust independent elementary features",
           http://cvlabwww.epfl.ch/~lepetit/papers/calonder_eccv10.pdf

    Examples
    --------
    >> from skimage.feature import corner_peaks, corner_harris, \\
    ..   pairwise_hamming_distance, brief, match_keypoints_brief
    >> square1 = np.zeros([8, 8], dtype=np.int32)
    >> square1[2:6, 2:6] = 1
    >> square1
    array([[0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 1, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
    >> keypoints1 = corner_peaks(corner_harris(square1), min_distance=1)
    >> keypoints1
    array([[2, 2],
           [2, 5],
           [5, 2],
           [5, 5]])
    >> descriptors1, keypoints1 = brief(square1, keypoints1, patch_size=5)
    >> keypoints1
    array([[2, 2],
           [2, 5],
           [5, 2],
           [5, 5]])
    >> square2 = np.zeros([9, 9], dtype=np.int32)
    >> square2[2:7, 2:7] = 1
    >> square2
    array([[0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 1, 1, 1, 1, 1, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0],
           [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
    >> keypoints2 = corner_peaks(corner_harris(square2), min_distance=1)
    >> keypoints2
    array([[2, 2],
           [2, 6],
           [6, 2],
           [6, 6]])
    >> descriptors2, keypoints2 = brief(square2, keypoints2, patch_size=5)
    >> keypoints2
    array([[2, 2],
           [2, 6],
           [6, 2],
           [6, 6]])
    >> pairwise_hamming_distance(descriptors1, descriptors2)
    array([[ 0.03125  ,  0.3203125,  0.3671875,  0.6171875],
           [ 0.3203125,  0.03125  ,  0.640625 ,  0.375    ],
           [ 0.375    ,  0.6328125,  0.0390625,  0.328125 ],
           [ 0.625    ,  0.3671875,  0.34375  ,  0.0234375]])
    >> match_keypoints_brief(keypoints1, descriptors1,
    ..                       keypoints2, descriptors2)
    array([[[ 2,  2],