<?php

// time that a new post stays editable for
define('LS_GRACE_PERIOD', "15 minutes ago");
  
// -------------------------------------------------------------------------------------------------
class ListopiaCore
{
  protected $ldb = NULL;
  public function Database() { return $this->ldb; }
  
  // UI generator helpers
  protected $ui_login = NULL;
  protected $ui_misc = NULL;
  public function UI_Login() { return $this->ui_login; }
  public function UI_Misc() { return $this->ui_misc; }
  
  // -----------------------------------------------------------------------------------------------
  function getNews()
  {
    $query = $this->ldb->select(array(
                        'table' => 'news',
                        'order' => 'timestamp_utc desc'
                        ));
    return $query;
  }
    
  // -----------------------------------------------------------------------------------------------
  // get the total number of lists on the site
  function getListCount()
  {
    $query = $this->ldb->query('select count(*) as counter from t_lists', false, false);
    if (!empty($query[0]))
    {
      if (isset($query[0]['counter']))
        return $query[0]['counter'];
    }
    
    return 0;
  }
  
  // -----------------------------------------------------------------------------------------------
  // get the total number of users, active or otherwise
  function getUserCounts()
  {
    $stats = array(
      'total' => 0,
      'active' => 0
    );

    $query = $this->ldb->query('select count(*) as counter from users');

    if (!empty($query[0]))
    {
      if (isset($query[0][0]['counter']))
        $stats['total'] = intval($query[0][0]['counter']);
    }
    
    $query = $this->ldb->query('select count(*) as counter from users where users.user_score != 0');
    if (!empty($query[0]))
    {
      if (isset($query[0][0]['counter']))
        $stats['active'] = intval($query[0][0]['counter']);
    }
    
    return $stats;
  }
  
  // -----------------------------------------------------------------------------------------------
  function getListopiaStats()
  {
    $stats = array(
      'start' => 'unknown',
      'start_days' => '0 days ago',
      'num_items' => 0
    );
    
    $query = $this->ldb->select(array(
                    'fields' => 't_items.item_created',
                    'table' => 't_items',
                    'order' => 'item_created asc',
                    'limit' => 1
                    ));
    
    if (!empty($query[0]))
    {
      $dateFrom = new DateTime("now");
      $dateTo = new DateTime($query[0]['t_items']['item_created']);
      $interval = $dateTo->diff($dateFrom);
      $daysElapsed = $interval->format('%a days ago');
      
      $stats['start'] = date("F, Y", strtotime($query[0]['t_items']['item_created']));
      $stats['start_days'] = $daysElapsed;
    }
    
    $query = $this->ldb->query('select count(*) as counter from t_items');
    if (!empty($query[0]))
    {
      if (isset($query[0][0]['counter']))
        $stats['num_items'] = intval($query[0][0]['counter']);
    }
    
    return $stats;
  }
  
  // -----------------------------------------------------------------------------------------------
  // update a visit count for the given user on the chosen list
  function incListVisitCount($user, $list) 
  {
    $queryCondition = "user_id = ".((int)$user)." and list_id = ".((int)$list);
    
    $query = $this->ldb->select(array(
                        'fields' => 'visit_count',
                        'table' => 'last_visits',
                        'condition' => $queryCondition,
                        'limit' => 1
                        ));
    if (empty($query[0]))
    {
      $date = date("Y-m-d H:i:s", time());
      $data = array(
    
        'user_id'           => array(((int)Session::getInstance()->gl_userid)),
        'list_id'           => array(((int)$list)),
        'last_visit'        => $date,
        'visit_count'       => 1
      );
      $ok = $this->ldb->insert('last_visits', $data);
    }
    else
    {
      $data = array(
        'visit_count' => array( 'visit_count + 1' )
      );
      $ok = $this->ldb->update('last_visits', $data, $queryCondition);
    }
  }
  
  // -----------------------------------------------------------------------------------------------
  function getListData($listID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 't_lists.*, users.user_name, users.user_id',
                        'table' => 't_lists',
                        'join' => 'users on t_lists.list_createdby = users.user_id',
                        'condition' => 't_lists.list_id = ' . ((int)$listID),
                        'limit' => 1
                        ));
    return $query;
  }

  // -----------------------------------------------------------------------------------------------
  function getListBlurb($listID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 't_lists.list_blurb',
                        'table' => 't_lists',
                        'condition' => 't_lists.list_id = ' . ((int)$listID),
                        'limit' => 1
                        ));
    return $query;
  }
  
  // -----------------------------------------------------------------------------------------------
  function isImageList($listID)
  {
    $isImageList = false;
    $query = $this->ldb->select(array(
                    'fields' => 'list_type',
                    'table' => 't_lists',
                    'condition' => 'list_id = ' . ((int)$listID)
                    ));
    if (!empty($query[0]))
    {
      $isImageList = ($query[0]['t_lists']['list_type'] == 'image');
    }
    
    return $isImageList;    
  }
  
  // -----------------------------------------------------------------------------------------------
  function getListMinimumEntries($listID)
  {
    $entryCount = 5;
    $query = $this->ldb->select(array(
                    'fields' => 'list_type',
                    'table' => 't_lists',
                    'condition' => 'list_id = ' . ((int)$listID)
                    ));
    if (!empty($query[0]))
    {
      if ($query[0]['t_lists']['list_type'] == 'image')
        $entryCount = 2;
    }
    
    return $entryCount;    
  }  
  
  // -----------------------------------------------------------------------------------------------
  function getListEntries($listID, $sorting = 'score', $getRejected = false)
  {
    $isImageList = $this->isImageList($listID);
                    
    // choose a sort order; default to time
    switch ($sorting)
    {
      default:
      case 'score':
        $orderBy = "vote_score desc, t_items.item_votesup desc";
        break;
        
      case 'time':
        $orderBy = "t_items.item_created asc";
        break;
      case 'newest':
        $orderBy = "t_items.item_created desc";
        break;
      case 'worst':
        $orderBy = "vote_score asc, t_items.item_votesdown desc";
        break;
      case 'user':
        $orderBy = "users.user_name asc, vote_score desc";
        break;
    }
    
    $extraCondition = ($isImageList ? " and t_items.item_extra = \"image\"" : "");
    
    if ($getRejected)
      $extraCondition .= " and t_items.item_rejected = \"y\"";
    else
      $extraCondition .= " and t_items.item_rejected = \"n\"";

    $query = $this->ldb->select(array(
                        'fields' => 't_items.*, users.user_name, users.user_id, (t_items.item_votesup - t_items.item_votesdown) as vote_score',
                        'table' => 't_items',
                        'join' => 'users on users.user_id = t_items.item_createdby',
                        'condition' => 't_items.item_list = ' . ((int)$listID) . $extraCondition,
                        'order' => $orderBy
                        ));
    return $query;
  }
  
  // -----------------------------------------------------------------------------------------------
  function getRejectedItemCount($listID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 'count(*) as counter',
                        'table' => 't_items',
                        'condition' => 't_items.item_rejected = "y" and t_items.item_list = ' . ((int)$listID)
                        ));
    return $query[0][0]['counter'];
  }
  
  // -----------------------------------------------------------------------------------------------
  function getNumListEntries($listID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 'count(*) as counter',
                        'table' => 't_items',
                        'condition' => 't_items.item_list = ' . ((int)$listID)
                        ));
    return $query;
  }
  
  
  // -----------------------------------------------------------------------------------------------
  function getListEntryComments($listID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 't_discussion.*, t_items.item_list',
                        'table' => 't_discussion',
                        'join' => 't_items on t_discussion.disc_item = t_items.item_id and t_items.item_list = ' . ((int)$listID),
                        'order' => 't_discussion.disc_datetime asc'
                        ));
    
    $disc = array();
    
    // sort into item-buckets
    foreach ($query as &$row)
    {
      $discID = $row['t_discussion']['disc_item'];
      if (!isset($disc[ $discID ]))
        $disc[ $discID ] = array();
        
      array_push($disc[ $discID ], $row);
    }
    
    return $disc;
  }
  
  // -----------------------------------------------------------------------------------------------
  function getImageListAdornmentHTML()
  {
    return "<img src='images/picture_list.png' width='16' height='16' style='vertical-align: text-bottom; margin-left: 6px;'/>";
  }
  
  // -----------------------------------------------------------------------------------------------
  function defaultFormatListPost($post)
  {
    if ($post['t_items']['item_extra'] == 'image')
    {
      $postContent = stripslashes($post['t_items']['item_blurb']);
      printf("<img style='margin:4px auto 4px auto;' class='ui-corner-all lst-avatar-img' src='%s'/>", $postContent);
    }
    else
    {
      $postContent = ConditionTextForDisplay($post['t_items']['item_blurb']);
      printf("<p>&quot;%s&quot;</p>", $postContent);
    }  
  }
  
  // -----------------------------------------------------------------------------------------------
  function isListOnlyOpenToAuthor($listFeat, $listSub)
  {
    return ($listFeat == 'only you' || ($listSub != 'members' && $listFeat != 'everyone'));
  }
  
  // -----------------------------------------------------------------------------------------------
  function getListComments($listID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 't_discussion.*',
                        'table' => 't_discussion',
                        'condition' => 't_discussion.disc_item = -1 and t_discussion.disc_list = ' . ((int)$listID),
                        'order' => 't_discussion.disc_datetime asc'
                        ));
    
    return $query;
  }
    
  // -----------------------------------------------------------------------------------------------
  function getSingleListItemDiscussion($listItemID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 't_discussion.*',
                        'table' => 't_discussion',
                        'condition' => 't_discussion.disc_item = ' . ((int)$listItemID),
                        'order' => 't_discussion.disc_datetime asc'
                        ));
    
    return $query;
  }
  
  // -----------------------------------------------------------------------------------------------
  function getListStats($listID)
  {
    $stats = array(
      'visits' => 0,
      'rejected' => 0,
    );
    
    $query = $this->ldb->select(array(
                        'fields' => 'SUM(visit_count) as counter',
                        'table' => 'last_visits',
                        'condition' => 'last_visits.list_id = ' . ((int)$listID),
                        'limit' => 1
                        ));
    if (!empty($query[0]) && isset($query[0][0]['counter']))
      $stats['visits'] = $query[0][0]['counter'];

    return $stats;
  }
  
  // -----------------------------------------------------------------------------------------------
  function getListVote($listID)
  {
    $stats = array(
      'upvote' => 0,
      'downvote' => 0,
    );
    
    $query = $this->ldb->select(array(
                        'fields' => 'SUM(vote) as counter',
                        'table' => 'listvotes',
                        'condition' => 'listvotes.list = '.((int)$listID).' and vote = 1'
                        ));
    if (!empty($query[0]) && isset($query[0][0]['counter']))
      $stats['upvote'] = $query[0][0]['counter'];

    $query = $this->ldb->select(array(
                        'fields' => 'SUM(vote) as counter',
                        'table' => 'listvotes',
                        'condition' => 'listvotes.list = '.((int)$listID).' and vote = -1'
                        ));
    if (!empty($query[0]) && isset($query[0][0]['counter']))
      $stats['downvote'] = $query[0][0]['counter'];
      
    return $stats;
  }  

  // -----------------------------------------------------------------------------------------------
  function listIDIsValid($listID)
  {
    if (!is_numeric($listID))
      return false;
      
    if ($listID >= 9999)
      return true;

    $query = $this->ldb->select(array(
                        'fields' => 'list_id',
                        'table' => 't_lists',
                        'condition' => 'list_id = '.((int)$listID)
                        ));

    return (!empty($query[0]['t_lists']['list_id']));
  }
  
  // -----------------------------------------------------------------------------------------------
  function listItemIDIsValid($listItemID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 'item_id',
                        'table' => 't_items',
                        'condition' => 'item_id = '.((int)$listItemID)
                        ));

    return (!empty($query[0]['t_items']['item_id']));
  }
  
  // -----------------------------------------------------------------------------------------------
  function getMessageStats()
  {
    $sesh = Session::getInstance();
    if (isset($sesh->gl_loggedin))
    {
      $stats = array(
        'unread' => 0,    // inbox
        'archived' => 0,
        'sent' => 0
      );
      
      // get unread + archived counts
      $query = $this->ldb->select(array(
                    'fields' => 'mess_to_status, COUNT(*) as counter',
                    'table' => 'messages',
                    'condition' => 'mess_to = '.$sesh->gl_userid,
                    'group' => 'mess_to_status'
                    ), false, false);
      
      foreach ($query as &$row)
      {
        $stats[ $row['messages']['mess_to_status'] ] = 
          $row[0]['counter'];
      }

      // get sent counts
      $query = $this->ldb->select(array(
                    'fields' => 'COUNT(*) as counter',
                    'table' => 'messages',
                    'condition' => 'mess_from = '.$sesh->gl_userid
                    ), false, false);
                    
      if (!empty($query[0]))
      {
        $stats['sent'] = $query[0][0]['counter'];
      }
      
      return $stats;
    }
    else die("Message stats only available when logged in");
  }
  
  // -----------------------------------------------------------------------------------------------
  function getMessageData($msgStatus, $userID = -1)
  {
    $sesh = Session::getInstance();
    if (isset($sesh->gl_loggedin))
    {
      $uid = ($userID == -1) ? $sesh->gl_userid : ((int)$userID);
      
      $msgCondition = ($msgStatus == 'sent') ?
        'mess_from = '.$uid :
        'mess_to = '.$uid.' and mess_to_status = "'.$msgStatus.'"';

      $msgJoin = ($msgStatus == 'sent') ?
        'users on users.user_id = mess_to' :
        'users on users.user_id = mess_from';
                
      $query = $this->ldb->select(array(
                  'fields' => 'messages.*, users.user_name, users.user_id',
                  'table' => 'messages',
                  'join' => $msgJoin,
                  'condition' => $msgCondition,
                  'order' => 'mess_sent desc'
                  ));
      
      return $query;
    }
    else die("Message stats only available when logged in");
  }
  
  // -----------------------------------------------------------------------------------------------
  function modifyMessage($id, $op)
  {
    $sesh = Session::getInstance();
    if (isset($sesh->gl_loggedin))
    {
      switch ($op)
      {
        case "archived": 
          $data = array(
            'mess_to_status' => array("'archived'")
          );
          break;
          
        case "unread": 
          $data = array(
            'mess_to_status' => array("'unread'")
          );
          break;          
        
        default:
          die("unknown operation on message");
          break;
      }
      $this->ldb->update('messages', $data, "mess_id = ".((int)$id) );
    }
    else die("You can't modify messages while logged out");
  }
  
  // -----------------------------------------------------------------------------------------------
  function userIDIsValid($userID)
  {
    $query = $this->ldb->select(array(
                        'fields' => 'user_id',
                        'table' => 'users',
                        'condition' => 'user_id = '.((int)$userID)
                        ));

    return (!empty($query[0]['users']['user_id']));
  }  
  
  // -----------------------------------------------------------------------------------------------
  function getUserData($userID)
  {
    $query = $this->ldb->select(array(
                        'fields' => '*',
                        'table' => 'users',
                        'condition' => 'user_id = '.((int)$userID),
                        'limit' => 1
                        ));
    return $query;
  }
  
  // -----------------------------------------------------------------------------------------------
  function pushPublish($pushMsg)
  {
  /*
    $pubnub = new Pubnub(
      'pub-93057603-3094-412d-bac3-437760c576a5', 
      'sub-ef1a5e4c-208d-11e2-a767-3daca9d9a3d1',
      'sec-ZTQ1NDI3YmQtMzM5ZS00YmFkLTkwNzgtMzE5YzI2YzQ0NTUy',
      false,
      false);
    
    $info = $pubnub->publish(array(
        'channel' => 'listopia_push',
        'message' => $pushMsg
    ));
  */
  }

  // -----------------------------------------------------------------------------------------------
  function searchQuery( $searchInput, $searchMode )
  {
    $cleanQuery = filter_var($searchInput, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
    $cleanQuery = str_replace("'", "\"", $cleanQuery);

    if ( $searchMode == 0 )
    {
      $query = $this->ldb->query("SELECT item_id FROM t_items WHERE MATCH(item_blurb) AGAINST ('".$cleanQuery."' IN BOOLEAN MODE) ORDER BY item_created DESC LIMIT 100");
    }
    if ( $searchMode == 1 )
    {
      $query = $this->ldb->query("SELECT * FROM t_discussion WHERE MATCH(disc_comment) AGAINST ('".$cleanQuery."' IN BOOLEAN MODE) ORDER BY disc_datetime DESC LIMIT 100");
    }

    return $query;
  }

  // -----------------------------------------------------------------------------------------------
  // constructor called by initial call to getInstance
  protected function init() 
  {
    $this->ldb = new ListopiaDB();
    
    $this->ui_login = new UILogin($this);
    $this->ui_misc  = new UIMisc($this);
  }
  
  protected function __construct() {} // block other forms of external construction
}