// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/BLERange.java
// public enum BLERange {
//     IMMIDIATE(0, 1), NEAR(1, 10),  FAR(10, Double.MAX_VALUE);
// 
//     public static BLERange getRange(double distance) {
//         for (BLERange range: BLERange.values()) {
//             if (range.isWithinRange(distance)) return range;
//         }
//         return FAR;
//     }
//     
//     BLERange(double bottomThreshold, double topThreshold) {
//         this.topThreshold = topThreshold;
//         this.bottomThreshold = bottomThreshold;
//     }
// 
//     private final double topThreshold;
//     private final double bottomThreshold;
//     
//     public boolean isWithinRange(double distance) {
//         return (distance <= topThreshold) && (distance > bottomThreshold);
//     }
// }
// 
// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/BLERangeChange.java
// public class BLERangeChange {
//     private final BLERange range;
//     private final long timestamp;
// 
//     public BLERangeChange(BLERange range, long timestamp) {
//         this.range = range;
//         this.timestamp = timestamp;
//     }
// 
//     public BLERange getRange() {
//         return range;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// }
// 
// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/DeviceFootprint.java
// public class DeviceFootprint implements Serializable {
// 
//     private String uuid;
// 
//     private int major;
// 
//     private int minor;
// 
//     public DeviceFootprint() {}
// 
//     /**
//      * Create new footprint
//      * @param uuid uuid of the device
//      * @param major major of the device
//      * @param minor minor of the device
//      */
//     public DeviceFootprint(String uuid, int major, int minor) {
//         this.uuid = uuid;
//         this.major = major;
//         this.minor = minor;
//     }
// 
//     public String getUuid() {
//         return uuid;
//     }
// 
//     public int getMajor() {
//         return major;
//     }
// 
//     public int getMinor() {
//         return minor;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         DeviceFootprint that = (DeviceFootprint) o;
// 
//         if (major != that.major) return false;
//         if (minor != that.minor) return false;
//         if (!uuid.equals(that.uuid)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = uuid.hashCode();
//         result = 31 * result + major;
//         result = 31 * result + minor;
//         return result;
//     }
// }
// 
// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/IBeaconDetect.java
// public class IBeaconDetect {
//     
//     private final DeviceFootprint footprint;
//     private final int rssi;
//     private final Date detectTime;
//     private final int txPower;
// 
//     public IBeaconDetect(String uuid, int major, int minor, int rssi, int txPower) {
//         footprint = new DeviceFootprint(uuid.toLowerCase(), major, minor);
//         this.rssi = rssi;
//         this.detectTime = new Date();
//         this.txPower = txPower;
//     }
// 
//     public DeviceFootprint getFootprint() {
//         return footprint;
//     }
// 
//     public int getRssi() {
//         return rssi;
//     }
// 
//     public Date getDetectTime() {
//         return detectTime;
//     }
//     
//     public double getDistance() {
//         return Math.sqrt(Math.pow(10, (txPower - rssi) / 10.0));
//     }
//     
//     public BLERange getRange(){
//         return BLERange.getRange(getDistance());
//         
//     }
//     
// }


import android.util.Log;
import com.orange.beaconme_sdk.ble.model.BLERange;
import com.orange.beaconme_sdk.ble.model.BLERangeChange;
import com.orange.beaconme_sdk.ble.model.DeviceFootprint;
import com.orange.beaconme_sdk.ble.model.IBeaconDetect;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
        if (makeInvisibleTask != null) {
            makeInvisibleTask.cancel();
        }
        timer.purge();
        makeInvisibleTask = getMakeInvisibleTask();
        timer.schedule(makeInvisibleTask, VISIBILITY_DELAY);
    }


    @Override
    protected void handleDetection(IBeaconDetect detection) {
        rescheduleInvisibilityTask();
        onNewRangeCome(detection.getRange());
    }

    private void onNewRangeCome(BLERange newRange) {
        rangeChangesStack.add(new BLERangeChange(newRange, System.currentTimeMillis()));
        BLERangeChange rangeChange = rangeChangesStack.get(0);
        while (rangeChange.getTimestamp() < System.currentTimeMillis() - SAFE_INTERVAL) {
            rangeChangesStack.remove(rangeChange);
            rangeChange = rangeChangesStack.get(0);
        }

        checkRangeChanging();
    }

    private void checkRangeChanging() {
        BLERange lowestRange = rangeChangesStack.get(0).getRange();
        BLERange highestRange = rangeChangesStack.get(0).getRange();

// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/BLERange.java
// public enum BLERange {
//     IMMIDIATE(0, 1), NEAR(1, 10),  FAR(10, Double.MAX_VALUE);
// 
//     public static BLERange getRange(double distance) {
//         for (BLERange range: BLERange.values()) {
//             if (range.isWithinRange(distance)) return range;
//         }
//         return FAR;
//     }
//     
//     BLERange(double bottomThreshold, double topThreshold) {
//         this.topThreshold = topThreshold;
//         this.bottomThreshold = bottomThreshold;
//     }
// 
//     private final double topThreshold;
//     private final double bottomThreshold;
//     
//     public boolean isWithinRange(double distance) {
//         return (distance <= topThreshold) && (distance > bottomThreshold);
//     }
// }
// 
// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/BLERangeChange.java
// public class BLERangeChange {
//     private final BLERange range;
//     private final long timestamp;
// 
//     public BLERangeChange(BLERange range, long timestamp) {
//         this.range = range;
//         this.timestamp = timestamp;
//     }
// 
//     public BLERange getRange() {
//         return range;
//     }
// 
//     public long getTimestamp() {
//         return timestamp;
//     }
// }
// 
// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/DeviceFootprint.java
// public class DeviceFootprint implements Serializable {
// 
//     private String uuid;
// 
//     private int major;
// 
//     private int minor;
// 
//     public DeviceFootprint() {}
// 
//     /**
//      * Create new footprint
//      * @param uuid uuid of the device
//      * @param major major of the device
//      * @param minor minor of the device
//      */
//     public DeviceFootprint(String uuid, int major, int minor) {
//         this.uuid = uuid;
//         this.major = major;
//         this.minor = minor;
//     }
// 
//     public String getUuid() {
//         return uuid;
//     }
// 
//     public int getMajor() {
//         return major;
//     }
// 
//     public int getMinor() {
//         return minor;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         DeviceFootprint that = (DeviceFootprint) o;
// 
//         if (major != that.major) return false;
//         if (minor != that.minor) return false;
//         if (!uuid.equals(that.uuid)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = uuid.hashCode();
//         result = 31 * result + major;
//         result = 31 * result + minor;
//         return result;
//     }
// }
// 
// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/ble/model/IBeaconDetect.java
// public class IBeaconDetect {
//     
//     private final DeviceFootprint footprint;
//     private final int rssi;
//     private final Date detectTime;
//     private final int txPower;
// 
//     public IBeaconDetect(String uuid, int major, int minor, int rssi, int txPower) {
//         footprint = new DeviceFootprint(uuid.toLowerCase(), major, minor);
//         this.rssi = rssi;
//         this.detectTime = new Date();
//         this.txPower = txPower;
//     }
// 
//     public DeviceFootprint getFootprint() {
//         return footprint;
//     }
// 
//     public int getRssi() {
//         return rssi;
//     }
// 
//     public Date getDetectTime() {
//         return detectTime;
//     }
//     
//     public double getDistance() {
//         return Math.sqrt(Math.pow(10, (txPower - rssi) / 10.0));
//     }
//     
//     public BLERange getRange(){
//         return BLERange.getRange(getDistance());
//         
//     }
//     
// }


// Path: beacontag_sdk/src/main/java/com/orange/beaconme_sdk/control/detection_handlers/AreaHandler.java
import android.util.Log;
import com.orange.beaconme_sdk.ble.model.BLERange;
import com.orange.beaconme_sdk.ble.model.BLERangeChange;
import com.orange.beaconme_sdk.ble.model.DeviceFootprint;
import com.orange.beaconme_sdk.ble.model.IBeaconDetect;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

        if (makeInvisibleTask != null) {
            makeInvisibleTask.cancel();
        }
        timer.purge();
        makeInvisibleTask = getMakeInvisibleTask();
        timer.schedule(makeInvisibleTask, VISIBILITY_DELAY);
    }


    @Override
    protected void handleDetection(IBeaconDetect detection) {
        rescheduleInvisibilityTask();
        onNewRangeCome(detection.getRange());
    }

    private void onNewRangeCome(BLERange newRange) {
        rangeChangesStack.add(new BLERangeChange(newRange, System.currentTimeMillis()));
        BLERangeChange rangeChange = rangeChangesStack.get(0);
        while (rangeChange.getTimestamp() < System.currentTimeMillis() - SAFE_INTERVAL) {
            rangeChangesStack.remove(rangeChange);
            rangeChange = rangeChangesStack.get(0);
        }

        checkRangeChanging();
    }

    private void checkRangeChanging() {
        BLERange lowestRange = rangeChangesStack.get(0).getRange();
        BLERange highestRange = rangeChangesStack.get(0).getRange();

        for (BLERangeChange rangeChange: rangeChangesStack) {