/*
 * Copyright 2014-2016, Armenak Grigoryan, Matthew Eaton, and individual contributors as indicated
 * by the @authors tag. See the copyright.txt in the distribution for a
 * full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */
package com.strider.datadefender.extensions;

import com.strider.datadefender.anonymizer.functions.Core;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;

import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;

/**
 * @author Matthew Eaton
 */
@Log4j2
public class BiographicFunctions extends Core {

    private static String prependZero(final int num) {
        String dayStr;

        if (num <= 9) {
            dayStr = '0' + String.valueOf(num);
        } else {
            dayStr = String.valueOf(num);
        }

        return dayStr;
    }

    private static int randBetween(final int start, final int end) {
        return start + (int) Math.round(Math.random() * (end - start));
    }

    /**
     * Generates random 9-digit social insurance number
     * @return String
     * @throws java.text.ParseException
     */
    public java.sql.Date randomBirthDate() throws java.text.ParseException {
        final GregorianCalendar gc   = new GregorianCalendar();
        final int               year = randBetween(1900, 2016);

        gc.set(GregorianCalendar.YEAR, year);

        final int dayOfYear = randBetween(1, gc.getActualMaximum(GregorianCalendar.DAY_OF_YEAR));

        gc.set(GregorianCalendar.DAY_OF_YEAR, dayOfYear);

        final String birthDate = prependZero(gc.get(GregorianCalendar.DAY_OF_MONTH)) + "-"
                                 + prependZero(gc.get(GregorianCalendar.MONTH) + 1) + "-"
                                 + gc.get(GregorianCalendar.YEAR);

        log.debug("BirthDate:[" + birthDate + "]");

        final DateFormat    format = new SimpleDateFormat("dd-MM-yyyy", Locale.US);
        final java.sql.Date date   = new java.sql.Date(format.parse(birthDate).getTime());

        log.debug("Generated BirthDate:[" + date.toString() + "]");

        return date;
    }

    /**
     * Algorithm is taken from https://en.wikipedia.org/wiki/Social_Insurance_Number
     * @param sin
     * @return boolean true, if SIN is valid, otherwise false
     */
    public static boolean isValidSIN(final String sin) {
        boolean valid = false;

        if (sin.length() < 9) {
            log.debug("SIN length is < 9");

            return valid;
        }

        if (!StringUtils.isNumeric(sin)) {
            log.debug("SIN " + sin + " is not number");

            return valid;
        }

        final int[]         sinArray   = new int[sin.length()];
        final int[]         checkArray = {
            1, 2, 1, 2, 1, 2, 1, 2, 1
        };
        final List<Integer> sinList    = new ArrayList();

        log.info(sin);

        for (int i = 0; i < 9; i++) {
            sinArray[i] = Integer.valueOf(sin.substring(i, i + 1));
            sinArray[i] = sinArray[i] * checkArray[i];
        }

        int sum = 0;

        for (int i = 0; i < 9; i++) {
            final String tmp = String.valueOf(sinArray[i]);

            if (tmp.length() == 1) {
                sinList.add(Integer.valueOf(tmp));
                sum += Integer.valueOf(tmp);
            } else {
                sinList.add(Integer.valueOf(tmp.substring(0, 1)));
                sum += Integer.valueOf(tmp.substring(0, 1));
                sinList.add(Integer.valueOf(tmp.substring(1, 2)));
                sum += Integer.valueOf(tmp.substring(1, 2));
            }
        }

        if ((sum % 10) == 0) {
            valid = true;
        }

        return valid;
    }

    /**
     * Check if String represents a valid sin
     * @param sin String representing a sin
     * @return true if valid sin, false if not
     */

//  public boolean isValidSIN(final String sin) {
//      if (sin == null || sin.length() != 9 ) {
//          log.info("isValidSin: Step 0");
//          return false;
//      }
//      int[] sinDigits = new int[sin.length()];
//      log.info("isValidSin: Step 1");
//                  
//      for (int i=0; i<sin.length(); i++) {
//          sinDigits[i] = Integer.parseInt(sin.substring(i, i+1));
//      }
//
//      return (isValidSIN(sinDigits));
//  }
}


//~ Formatted by Jindent --- http://www.jindent.com

@@ -849,171 +849,45 @@
 ava.
-text.DateFormat;%0Aimport java.text.SimpleDateFormat;%0A%0Aimport java.util.ArrayList;%0Aimport java.util.GregorianCalendar;%0Aimport java.util.List;%0Aimport java.util.Locale
+util.ArrayList;%0Aimport java.util.List
 ;%0A%0Ai
@@ -1060,1527 +1060,8 @@
  %7B%0A%0A
-    private static String prependZero(final int num) %7B%0A        String dayStr;%0A%0A        if (num %3C= 9) %7B%0A            dayStr = '0' + String.valueOf(num);%0A        %7D else %7B%0A            dayStr = String.valueOf(num);%0A        %7D%0A%0A        return dayStr;%0A    %7D%0A%0A    private static int randBetween(final int start, final int end) %7B%0A        return start + (int) Math.round(Math.random() * (end - start));%0A    %7D%0A%0A    /**%0A     * Generates random 9-digit social insurance number%0A     * @return String%0A     * @throws java.text.ParseException%0A     */%0A    public java.sql.Date randomBirthDate() throws java.text.ParseException %7B%0A        final GregorianCalendar gc   = new GregorianCalendar();%0A        final int               year = randBetween(1900, 2016);%0A%0A        gc.set(GregorianCalendar.YEAR, year);%0A%0A        final int dayOfYear = randBetween(1, gc.getActualMaximum(GregorianCalendar.DAY_OF_YEAR));%0A%0A        gc.set(GregorianCalendar.DAY_OF_YEAR, dayOfYear);%0A%0A        final String birthDate = prependZero(gc.get(GregorianCalendar.DAY_OF_MONTH)) + %22-%22%0A                                 + prependZero(gc.get(GregorianCalendar.MONTH) + 1) + %22-%22%0A                                 + gc.get(GregorianCalendar.YEAR);%0A%0A        log.debug(%22BirthDate:%5B%22 + birthDate + %22%5D%22);%0A%0A        final DateFormat    format = new SimpleDateFormat(%22dd-MM-yyyy%22, Locale.US);%0A        final java.sql.Date date   = new java.sql.Date(format.parse(birthDate).getTime());%0A%0A        log.debug(%22Generated BirthDate:%5B%22 + date.toString() + %22%5D%22);%0A%0A        return date;%0A    %7D%0A%0A
     
@@ -2644,676 +2644,6 @@
   %7D%0A
-%0A    /**%0A     * Check if String represents a valid sin%0A     * @param sin String representing a sin%0A     * @return true if valid sin, false if not%0A     */%0A%0A//  public boolean isValidSIN(final String sin) %7B%0A//      if (sin == null %7C%7C sin.length() != 9 ) %7B%0A//          log.info(%22isValidSin: Step 0%22);%0A//          return false;%0A//      %7D%0A//      int%5B%5D sinDigits = new int%5Bsin.length()%5D;%0A//      log.info(%22isValidSin: Step 1%22);%0A//                  %0A//      for (int i=0; i%3Csin.length(); i++) %7B%0A//          sinDigits%5Bi%5D = Integer.parseInt(sin.substring(i, i+1));%0A//      %7D%0A//%0A//      return (isValidSIN(sinDigits));%0A//  %7D%0A%7D%0A%0A%0A//~ Formatted by Jindent --- http://www.jindent.com
+%7D
 %0A

Remove unused/commented out methods