<?php
class SurveyObj
{
    /**
    * @var int
    */
    public $id;

    /**
    * Whether the survey is anonymous or not.
    * @var boolean
    */
    public $anonymous;

    /**
    * Answer, codes, and full text to the questions.
    * This is used in conjunction with the fieldMap to produce
    * some of the more verbose output in a survey export.
    * array[recordNo][columnName]
    *
    * @var array[int][string]mixed
    */
    public $answers = array();

    /**
    * The fieldMap as generated by createFieldMap(...).
    * @var array[]mixed
    */
    public $fieldMap;

    /**
    * The groups in the survey.
    *
    * @var array[int][string]mixed
    */
    public $groups;
    
    /**
     * info about the survey
     * 
     * @var array
     */
    public $info;

    /**
    * The questions in the survey.
    *
    * @var array[int][string]mixed
    */
    public $questions;

    /**
    * The tokens in the survey.
    *
    * @var array[int][string]mixed
    */
    public $tokens;
    
    /**
     * When relevant holds the available fields from the token table
     * 
     * @var array[fieldname][localised description]
     */
    public $tokenFields = array();

    /**
    * Stores the responses to the survey in a two dimensional array form.
    * array[recordNo][fieldMapName]
    *
    * @var array[int][string]mixed
    */
    public $responses;

    /**
    *
    * @var array[int][string]mixed
    */
    public $languageSettings;
    
    /**
    * Returns question arrays ONLY for questions that are part of the
    * indicated group and are top level (i.e. no subquestions will be
    * returned).   If there are no then an empty array will be returned.
    * If $groupId is not set then all top level questions will be
    * returned regardless of the group they are a part of.
    */
    public function getQuestions($groupId = null)
    {
        $qs = array();
        foreach($this->questions as $q)
        {
            if ($q['parent_qid'] == 0)
            {
                if(empty($groupId) || $q['gid'] == $groupId)
                {
                    $qs[] = $q;
                }
            }
        }
        return $qs;
    }

    /**
    * Returns the question code/title for the question that matches the $fieldName.
    * False is returned if no matching question is found.
    * @param string $fieldName
    * @return string (or false)
    */
    public function getQuestionCode($fieldName)
    {
        if (isset($this->fieldMap[$fieldName]['title']))
        {
            return $this->fieldMap[$fieldName]['title'];
        }
        else
        {
            return false;
        }
    }

    public function getQuestionText($fieldName)
    {
        $question = $this->fieldMap[$fieldName];
        if ($question)
        {
            return $question['question'];
        }
        else
        {
            return false;
        }
    }


    /**
    * Returns all token records that have a token value that matches
    * the one given.  An empty array is returned if there are no
    * matching token records.
    *
    * @param mixed $token
    */
    public function getTokens($token)
    {
        $matchingTokens = array();

        foreach($this->tokens as $t)
        {
            if ($t['token'] == $token)
            {
                $matchingTokens[] = $t;
            }
        }

        return $matchingTokens;
    }

    /**
    * Returns an array containing all child question rows for the given parent
    * question ID.  If no children are found then an empty array is
    * returned.
    *
    * @param int $parentQuestionId
    * @return array[int]array[string]mixed
    */
    public function getSubQuestionArrays($parentQuestionId)
    {
        $results = array();
        foreach ($this->questions as $question)
        {
            if ($question['parent_qid'] == $parentQuestionId)
            {
                $results[$question['qid']] = $question;
            }
        }
        return $results;
    }

    /**
    * Returns the full answer for the question that matches $fieldName
    * and the answer that matches the $answerCode.  If a match cannot
    * be made then false is returned.
    *
    * The name of the variable $answerCode is not strictly an answerCode
    * but could also be a comment entered by a participant.
    *
    * @param string $fieldName
    * @param string $answerCode
    * @param Translator $translator
    * @param string $sLanguageCode
    * @return string (or false)
    */
    public function getFullAnswer($fieldName, $answerCode, Translator $translator, $sLanguageCode)
    {
        $fullAnswer = null;
        $fieldType = $this->fieldMap[$fieldName]['type'];
        $question = $this->fieldMap[$fieldName];
        $questionId = $question['qid'];
        $answer = null;
        if ($questionId)
        {
            $answers = $this->getAnswers($questionId);
            if (isset($answers[$answerCode]))
            {
                $answer = $answers[$answerCode]['answer'];
            }
        }

        //echo "\n$fieldName: $fieldType = $answerCode";
        switch ($fieldType)
        {
            case 'R':   //RANKING TYPE
                $fullAnswer = $answer;
                break;

            case '1':   //Array dual scale
                if (mb_substr($fieldName, -1) == 0)
                {
                    $answers = $this->getAnswers($questionId, 0);
                }
                else
                {
                    $answers = $this->getAnswers($questionId, 1);
                }
                if (array_key_exists($answerCode, $answers))
                {
                    $fullAnswer = $answers[$answerCode]['answer'];
                }
                else
                {
                    $fullAnswer = null;
                }
                break;

            case 'L':   //DROPDOWN LIST
            case '!':
                if (mb_substr($fieldName, -5, 5) == 'other')
                {
                    $fullAnswer = $answerCode;
                }
                else
                {
                    if ($answerCode == '-oth-')
                    {
                        $fullAnswer = $translator->translate('Other', $sLanguageCode);
                    }
                    else
                    {
                        $fullAnswer = $answer;
                    }
                }
                break;

            case 'O':   //DROPDOWN LIST WITH COMMENT
                if (isset($answer))
                {
                    //This is one of the dropdown list options.
                    $fullAnswer = $answer;
                }
                else
                {
                    //This is a comment.
                    $fullAnswer = $answerCode;
                }
                break;

            case 'Y':   //YES/NO
            switch ($answerCode)
            {
                case 'Y':
                    $fullAnswer = $translator->translate('Yes', $sLanguageCode);
                    break;

                case 'N':
                    $fullAnswer = $translator->translate('No', $sLanguageCode);
                    break;

                default:
                    $fullAnswer = $translator->translate('N/A', $sLanguageCode);
            }
            break;

            case 'G':
            switch ($answerCode)
            {
                case 'M':
                    $fullAnswer = $translator->translate('Male', $sLanguageCode);
                    break;

                case 'F':
                    $fullAnswer = $translator->translate('Female', $sLanguageCode);
                    break;

                default:
                    $fullAnswer = $translator->translate('N/A', $sLanguageCode);
            }
            break;

            case 'M':   //MULTIOPTION
            case 'P':
                if (mb_substr($fieldName, -5, 5) == 'other' || mb_substr($fieldName, -7, 7) == 'comment')
                {
                    //echo "\n -- Branch 1 --";
                    $fullAnswer = $answerCode;
                }
                else
                {
                    if ($answerCode == 'Y') 
                    {
                        $fullAnswer = $translator->translate('Yes', $sLanguageCode);
                    } 
                    elseif ($answerCode == 'N' || $answerCode === '')   // Strict check for empty string to find null values
                    {
                        $fullAnswer = $translator->translate('No', $sLanguageCode);
                    } else {
                        $fullAnswer = $translator->translate('N/A', $sLanguageCode);
                    }
                }
                break;

            case 'C':
            switch ($answerCode)
            {
                case 'Y':
                    $fullAnswer = $translator->translate('Yes', $sLanguageCode);
                    break;

                case 'N':
                    $fullAnswer = $translator->translate('No', $sLanguageCode);
                    break;

                case 'U':
                    $fullAnswer = $translator->translate('Uncertain', $sLanguageCode);
                    break;
            }
            break;

            case 'E':
            switch ($answerCode)
            {
                case 'I':
                    $fullAnswer = $translator->translate('Increase', $sLanguageCode);
                    break;

                case 'S':
                    $fullAnswer = $translator->translate('Same', $sLanguageCode);
                    break;

                case 'D':
                    $fullAnswer = $translator->translate('Decrease', $sLanguageCode);
                    break;
            }
            break;

            case 'F':
            case 'H':
                $answers = $this->getAnswers($questionId, 0);
                $fullAnswer = (isset($answers[$answerCode])) ? $answers[$answerCode]['answer'] : "";
                break;

            default:

                $fullAnswer .= $answerCode;
        }

        return $fullAnswer;
    }

    /**
    * Returns an array of possible answers to the question.  If $scaleId is
    * specified then only answers that match the $scaleId value will be
    * returned. An empty array may be returned by this function if answers 
    * are found that match the questionId.
    *
    * @param int $questionId
    * @param int $scaleId
    * @return array[string]array[string]mixed (or false)
    */
    public function getAnswers($questionId, $scaleId = '0')
    {
        if(isset($this->answers[$questionId]) && isset($this->answers[$questionId][$scaleId]))
        {
            return $this->answers[$questionId][$scaleId];
        }
        return array();
    }
}