<?php
namespace App\Core;
use PDO;

abstract class AbstractRepository {

  protected $pdo;
//************************************************************************
  public function __construct(PDO $pdo) {
    $this->pdo = $pdo;
  }
//************************************************************************
  abstract public function getTableName();
  abstract public function getModelName();
//************************************************************************
  function all() {
    $table = $this->getTableName();
    $model = $this->getModelName();

    $strSQL = "SELECT * FROM `$table`
               ORDER BY last_name, day_of_birth";
    $stmt = $this->pdo->query($strSQL);
    $persons = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    return $persons;
  }

//****************************** nach Alter aufsteigend *******************
    function allByBirthday() {
      $table = $this->getTableName();
      $model = $this->getModelName();

      $strSQL = "SELECT * FROM `$table`
                 ORDER BY day_of_birth, last_name";
      $stmt = $this->pdo->query($strSQL);
      $persons = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
      return $persons;
    }
//************************************************************************
    function allNamesBySex($sex) {
      $table = $this->getTableName();
      $model = $this->getModelName();

      $strSQL = "SELECT member_id, first_name, last_name, father_id, birth_name, gender,
                  day_of_birth, place_of_birth
                 FROM `$table`
                 WHERE gender = '$sex'
                 ORDER BY last_name, day_of_birth";
      //$strSQL = "SELECT * FROM `$table` ORDER BY last_name, day_of_birth";
      $stmt = $this->pdo->query($strSQL);
      $persons = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
      return $persons;
    }

//************************************************************************
  function find($id) {
    $table = $this->getTableName();
    $model = $this->getModelName();

    $strSQL = "SELECT * FROM `$table` WHERE member_id = :id";
    $stmt = $this->pdo->prepare($strSQL);
    $stmt->execute(['id' => $id]);
    $stmt->setFetchMode(PDO::FETCH_CLASS, $model);
    $person = $stmt->fetch(PDO::FETCH_CLASS);
    return $person;
  }

//****************************** nachfahren Anfangsbuchstaben *************
  function findBy($char)  {
    $table = $this->getTableName();
    $model = $this->getModelName();

    if ($char != 'alle') {
      $strSQL = "SELECT * FROM `$table`
                  WHERE (UPPER(SUBSTRING(last_name,1,1))=\"".$char."\")
                  ORDER BY last_name, day_of_birth";
    } else {
      $strSQL = "SELECT * FROM `$table`
                  ORDER BY last_name, day_of_birth";
    }
    $stmt = $this->pdo->query($strSQL);
    $persons_char = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    return $persons_char;
  }

// ************************** Select father and mother of person by id
  function father($id) {
    $table = $this->getTableName();
    $model = $this->getModelName();

    $strSQL = "SELECT * FROM `$table`WHERE member_id = $id";
    // echo $strSQL;
    $stmt = $this->pdo->query($strSQL);
    $father = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    return $father;
  }

  // ************************** Select mother and mother of person by id
  function mother($id) {
    $table = $this->getTableName();
    $model = $this->getModelName();

    $strSQL = "SELECT mother_id FROM `$table`WHERE member_id = $id";
    $stmt = $this->pdo->query($strSQL);
    $mother = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    return $mother;
  }

// ***************** Select groups (children, siblings, couples, persons(sex))
  function children($id) {
    $table = $this->getTableName();
    $model = $this->getModelName();

    $strSQL = "SELECT member_id, first_name, last_name, birth_name, gender, member_img,
                    day_of_birth, place_of_birth, day_of_death, place_of_death, mother_id, father_id
              FROM `$table`
              WHERE (father_id = $id)
              UNION
              SELECT member_id, first_name, last_name, birth_name, gender, member_img,
                    day_of_birth, place_of_birth, day_of_death, place_of_death, mother_id, father_id
              FROM `$table`
              WHERE (mother_id = $id)
              ORDER BY day_of_birth";
    $stmt = $this->pdo->query($strSQL);
    $children = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    return $children;
    }

// Kindeskinder laden
  function child_children($id) {
    $table = $this->getTableName();
    $model = $this->getModelName();

    $strSQL = "SELECT member_id, first_name, last_name, birth_name, gender, member_img,
                day_of_birth, place_of_birth, day_of_death, place_of_death, mother_id, father_id
                FROM `$table`
               WHERE ((father_id = $id) OR (mother_id = $id))
               ORDER BY member_id";
    $stmt = $this->pdo->query($strSQL);
    $child_children = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    return $child_children;
  }

  // ************************** Select siblings of person by id
  function siblings($f_id, $id) {
    $table = $this->getTableName();
    $model = $this->getModelName();

    $strSQL = "SELECT * FROM `$table`
                        WHERE ((father_id = $f_id) AND (member_id != $id) AND (father_id != 0))
                        ORDER BY day_of_birth";
    $stmt = $this->pdo->query($strSQL);
    $siblings = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    return $siblings;
  }

  // ************************** Select unmarried people by sex and first charof last_name
  function ledige_char($sex,$char)  {
    $table = $this->getTableName();
    $model = $this->getModelName();

    if ($sex == 1){
      $str_sex = "man_id";
    } else {
      $str_sex = "woman_id";
    }

    if ($char != 'alle') {
      $strSQL = "SELECT member_id, first_name, last_name, day_of_birth, day_of_death, gender
                 FROM gen_member
                 WHERE (((UPPER(SUBSTRING(last_name,1,1))=\"".$char."\")
                 AND (gender = ".$sex.")) AND (member_id NOT IN (
                   SELECT ".$str_sex. " FROM gen_partner))) ORDER BY last_name";
    } else {
      $strSQL = "SELECT member_id, first_name, last_name, day_of_birth, day_of_death, gender
                 FROM gen_member
                 WHERE ((gender = ".$sex.") AND (member_id NOT IN (
                   SELECT ".$str_sex. " FROM gen_partner))) ORDER BY last_name";
    }
    $statement = $this->pdo->query($strSQL);
    $ledige = $statement->fetchALL(PDO::FETCH_CLASS, $model);
    return $ledige;
  }

// **************** returns a list of couples ****************************
  function couples($char){
    $table = $this->getTableName();
    $model = $this->getModelName();
    #echo "<br><br><br><br><br>".$table ." - ".$model."<br>";
    if ($char != "alle") {
      $WHERE = " AND (UPPER(SUBSTRING(last_name,1,1))=\"".$char."\")";
    } else {
      $WHERE = "";
    }
    #echo "<br><br><br><br>".$table; die();
    $strSQL_2 = "SELECT member_id, first_name, last_name, birth_name FROM `$table`
                 LEFT JOIN gen_partner ON gen_member.member_id = gen_partner.man_id
                 WHERE (gen_member.member_id = gen_partner.man_id) ".$WHERE. "
                 ORDER BY gen_partner.man_id";
    $statement = $this->pdo->query($strSQL_2);
    $par_men = $statement->fetchALL(PDO::FETCH_CLASS, $model);    //	 maried men
    //var_dump($par_men); die();

    $par_woman = array();
    foreach ($par_men as $man){
      $id = $man['member_id'];
      $gen = 02;

      $str_id = "gen_partner.woman_id";

      $strSQL = "SELECT * FROM gen_member
               LEFT JOIN gen_partner ON gen_member.member_id = $str_id
               WHERE ((man_id = $id) OR (woman_id = $id))
               ORDER BY par_von DESC";
      $stmt = $this->pdo->query($strSQL);
      $par_women[] = $stmt->fetchALL(PDO::FETCH_CLASS, $model);
    }

    $couples = array();
    $couple = array();
    $i = 0;
    foreach ($par_men as $man) {
      $couple = [
        'm_member_id' => $man['member_id'],
        'm_first_name' => $man['first_name'],
        'm_last_name' => $man['last_name'],
        'm_birth_name' => $man['birth_name'],
        'f_member_id' => $par_women[$i][0]['member_id'],
        'f_first_name' => $par_women[$i][0]['first_name'],
        'f_last_name' => $par_women[$i][0]['last_name'],
        'f_birth_name' => $par_women[$i][0]['birth_name'],
      ];
      $couples[] = $couple;
      //die();
      $i++;
    }
    return $couples;
  }

  // ******************** returns a lst of members by first char of last_name
  function parents($char){
    $table = $this->getTableName();
    $model = $this->getModelName();
    if ($char != "alle") {
      $WHERE = "((gen_m1.member_id = gen_member.father_id)  AND
           (gen_m2.member_id = gen_member.mother_id)) AND
           (UPPER(SUBSTRING(gen_member.last_name,1,1))=\"".$char."\")";
    } else {
      $WHERE = "((gen_m1.member_id = gen_member.father_id)  AND
           (gen_m2.member_id = gen_member.mother_id))";
    }
    $strSQL = "SELECT
          gen_member.member_id,
          gen_member.gender,
          gen_member.first_name,
          gen_member.last_name,
          gen_member.birth_name,
          gen_member.day_of_birth,
          gen_member.day_of_death,

          gen_m1.member_id AS m_member_id,
          gen_m1.first_name AS m_first_name,
          gen_m1.last_name AS m_last_name,
          gen_m1.birth_name AS m_birth_name,
          gen_m1.day_of_birth AS m_day_of_birth,
          gen_m1.day_of_death AS m_day_of_death,

          gen_m2.member_id AS f_member_id,
          gen_m2.first_name AS f_first_name,
          gen_m2.last_name AS f_last_name,
          gen_m2.birth_name AS f_birth_name,
          gen_m2.day_of_birth AS f_day_of_birth,
          gen_m2.day_of_death AS f_day_of_death
      FROM gen_member, gen_member AS gen_m1, gen_member AS gen_m2
      WHERE ".$WHERE.
      //" ORDER BY gen_member.last_name, gen_member.day_of_birth";
      " ORDER BY gen_member.last_name, gen_member.day_of_birth"; //member_id";
      //echo $strSQL; die;
    $statement = $this->pdo->query($strSQL);
    $parents = $statement->fetchALL(PDO::FETCH_CLASS, $model);
    return $parents;
  }

// ******************** returns a lst of members, father and mother and their children
  function family($char){
    $table = $this->getTableName();
    $model = $this->getModelName();
    //$char = "alle";
    if ($char != "alle") {
      $WHERE = "((gen_m1.member_id = gen_member.father_id)  AND
         (gen_m2.member_id = gen_member.mother_id)) AND
         (UPPER(SUBSTRING(gen_member.last_name,1,1))=\"".$char."\")";
    } else {
      $WHERE = "((gen_m1.member_id = gen_member.father_id)  AND
               (gen_m2.member_id = gen_member.mother_id))  ";
    }
    //if ($char == "alle") {$firstChar = "";} else {$firstChar = $char;}
    $strSQL = "SELECT gen_member.member_id, gen_member.first_name, gen_member.last_name, gen_member.father_id,
                      gen_m1.first_name AS m_first_name, gen_m1.last_name AS m_last_name,
                      gen_m2.first_name AS f_first_name, gen_m2.last_name AS f_last_name
              FROM gen_member, gen_member AS gen_m1, gen_member AS gen_m2
              WHERE ".$WHERE."
              ORDER BY gen_member.last_name, gen_member.day_of_birth";    //member_id";

      //echo $strSQL; die();
    $statement = $this->pdo->query($strSQL);
    $family = $statement->fetchALL(PDO::FETCH_CLASS, $model);
    return $family;
  }

//************************************************************************
  // Basis des Stammbaum (Parent_id = NULL)
  function get_root($baum){
    $table = $this->getTableName();
    $model = $this->getModelName();

    $p = 999;
    if ($baum != 0) {
      $strSQL = "SELECT * FROM gen_member
                 WHERE member_id = ".$baum."
                 ORDER BY last_name, day_of_birth";
    } else {
      $strSQL = "SELECT member_id, first_name, last_name, day_of_birth, parent_id
                  FROM gen_member
                  WHERE parent_id = $p
                  ORDER BY parent_id, member_id ASC";
    }
    //echo $strSQL; die();

    $statement = $this->pdo->query($strSQL);
    $root = $statement->fetchALL(PDO::FETCH_CLASS, $model);
    //var_dump($root); die();
    return $root;
  }
// ******************** update functions ****************************
  // ****************** update data for father and mother
    public function updateForFather($member_id, $father_id) {
      $table = $this->getTableName();
      $data = [
          'father_id' => $father_id,
          'member_id' => $member_id
      ];
      $sql = "UPDATE gen_member SET father_id=:father_id WHERE member_id=:member_id";
      $stmt= $this->pdo->prepare($sql);
      $stmt->execute($data);
    }

//************************************************************************
    public function updateForMother($member_id, $mother_id) {
      $table = $this->getTableName();
      $data = [
          'mother_id' => $mother_id,
          'member_id' => $member_id
      ];
      $sql = "UPDATE gen_member SET mother_id=:mother_id WHERE member_id=:member_id";
      $stmt= $this->pdo->prepare($sql);
      $stmt->execute($data);
    }
}
