import "../App.css";
import React, { useEffect, useState } from "react";
import { Container, Button, Form, Row, Col } from "react-bootstrap";
import { useLocation } from "react-router-dom";
import UseFetchFromEndpoint from "../hooks/useFetchFromEndpoint";
import check from "./check-mark.png";
import close from "./close.png";
import TextareaCounter from 'react-textarea-counter';
import { useNavigate } from "react-router-dom";

const postResponse = async (body, token) => {

  const response = await fetch(`http://localhost:8000/responses/`, {
    method: "POST",
    body: JSON.stringify(body),
    headers: { 'Authorization': `Token ${token}`,
               'Content-Type': `application/json`
             },
  });
  const status = response.status;

  return { status}; 
};

const putSectionEvaluated = async (body, id, token) => {

  const response = await fetch(`http://localhost:8000/students_in_sections/${id}/`, {
    method: "PUT",
    body: JSON.stringify(body),
    headers: { 'Authorization': `Token ${token}`,
               'Content-Type': `application/json`
             },
  });
  const status = response.status;

  return { status}; 
};

function Evaluation() {
  const location = useLocation();
  const studentData = location.state.studentData;
  const token = location.state.token;
  const courseid = location.state.courseid;
  const semester = location.state.semester;
  const id = location.state.id;

  const [genQuestionResponse] = UseFetchFromEndpoint(`/gen_questions/gen_question_per_semester/${semester}`, token)
  const [majorQuestionResponse] = UseFetchFromEndpoint(`/major_questions/major_questions_per_semester_id/${semester}`, token);
  const [outcomeResponse] = UseFetchFromEndpoint(`/outcomes/course_outcomes/${courseid}`, token)
  const [student_in_section] = UseFetchFromEndpoint(`/students_in_sections/student_evaluated/${studentData.user}/${id}`, token)
  const [major] = UseFetchFromEndpoint(`/majors/${studentData.major}`, token)
  const [genQuestionForm, setGenQuestionForm] = useState({})
  const [csQuestionForm, setCsQuestionForm] = useState({})
  const [majorQuestionForm, setMajorQuestionForm] = useState({})
  const [comments, setComments] = useState("")
  const [missingQuestions, setMissingQuestions] = useState("")
  const [isEvaluated, setIsEvaluated] = useState(null)
  const navigate = useNavigate();
  

  const handleSubmit = event => {
    event.preventDefault();

    let gen_answers = [];
    let cs_answers = [];
    let major_answers = [];

    var missed = [];
    var missedIndex = 0;

    //validate general questions
    let genKey = "gen";
    for (let i = 1; i <= genQuestionResponse.length; i++) {
      let updatedKey = genKey + String(i);
      var array = genQuestionForm[updatedKey];
      var counter = 0;
      for (let j = 0; j < 5; j++) {
        if (array[j] === 0)
          counter++;
        else 
          gen_answers.push(5 - j);
        if (counter === 5){
          var check = document.getElementById(String("gen" + i + "error"));
          check.style.display = "block";

          missed[missedIndex] = String(i)
          missedIndex++;
        }
      }                    
    }   
    
    //validate course specific questions
    let csKey = "cs";
    let csQuestionsPerOutcome;
    for (let i = 1; i <= Object.values(outcomeResponse[0])[2].length; i++) {
      csQuestionsPerOutcome = i;          
    }

    let counterStartSc = genQuestionResponse.length;
    for (let i = 0; i < outcomeResponse.length * csQuestionsPerOutcome; i++) {
      let updatedKey = csKey + String(counterStartSc + 1);
      let array = csQuestionForm[updatedKey];
      let counter = 0;
      for (let j = 0; j < 5; j++) {
        if (array[j] === 0)
          counter++;
        else 
          cs_answers.push(5 - j);
        if (counter === 5){
          let check = document.getElementById(String("cs" + (counterStartSc + 1) + "error"));
          check.style.display = "block";

          missed[missedIndex] = String(counterStartSc + 1)
          missedIndex++;
        }
      }       
      counterStartSc++;       
    } 

    //validate major questions
    let majorKey = "major";
    let majorQuestions;
    
    for (let i = 1; i <= majorQuestionResponse.length; i++) {
      if (Object.values(majorQuestionResponse[i - 1])[2] === major.id){
        for (let j = 1; j <= Object.values(majorQuestionResponse[i - 1])[1].length; j++) {
          majorQuestions = j;          
        }
      }   
    }
    
    let counterStart = genQuestionResponse.length + (outcomeResponse.length * csQuestionsPerOutcome);
    for (let i = 0; i < majorQuestions; i++) {
      let updatedKey = majorKey + String(counterStart + 1);
      let array = majorQuestionForm[updatedKey];
      let counter = 0;
      for (let j = 0; j < 5; j++) {
        if (array[j] === 0)
          counter++;
        else 
          major_answers.push(5 - j);
        if (counter === 5){
          let check = document.getElementById(String("major" + (counterStart + 1) + "error"));
          check.style.display = "block";

          missed[missedIndex] = String(counterStart + 1)
          missedIndex++;
        }
      }       
      counterStart++;       
    } 

    // To print missing questions as a message
    if (missed.length > 0){
      var str = "";
      if (missed.length !== 2){
        for (let i = 0; i < missed.length; i++) {      
          if (i === missed.length - 2)
            str = str + missed[i] + ", and "
          else if (i === missed.length - 1)
            str = str + missed[i];
          else
            str = str + missed[i] + ", ";
        }
      }
      else
        str = missed[0] + " and " + missed[1]; 

      let check = document.getElementById("missed");
      check.style.display = "block";
    }
    setMissingQuestions(str);
  
    if (missed.length === 0 && major) {
      let body = {
        "gen_answers" : gen_answers,
        "cs_answers" : cs_answers,
        "major_answers" : major_answers,
        "comments" : comments,
        "section" : id,
        "major" : major.id,
      }

      postResponse(body, token).then(({ status}) => {
        if (status === 201) {
          setIsEvaluated(true);
          
          let body_student_in_section = {
            "student" : studentData.user,
            "section" : id,
            "evaluated" : true,
          }
          putSectionEvaluated(body_student_in_section, student_in_section.id, token)
          //set flag, then continue

          navigate("/evaluation/confirm", {
            state: { username: studentData.user, token: token },
          });
        } else {
          navigate("/evaluation/error", {
            state: { username: studentData.user, token: token },
          });
        }
      });
    };
  };  
  
  const handleComment = event => {
    setComments(event.target.value);
  };

  const handleChange = event => { 

    // hide/show check-error icons
    var check = document.getElementById(event.target.name);
    if (document.getElementById(event.target.id).checked) {
      if (document.getElementById(String(event.target.name + "error")).style.display === "block") {
        document.getElementById(String(event.target.name + "error")).style.display = "none";
      }
      check.style.display = "block";
    }    

    //update requested dictionary
    var first2 = event.target.name.substring(0, 2);
    var dict;

    if (first2 === "ge")
      dict = genQuestionForm;
    else if (first2 === "cs")
      dict = csQuestionForm;
    else if (first2 === "ma")
      dict = majorQuestionForm;

    if (event.target.value === "1")
      dict[event.target.name] = [1,0,0,0,0];   
    else if (event.target.value === "2")
      dict[event.target.name] = [0,1,0,0,0];
    else if (event.target.value === "3")
      dict[event.target.name] = [0,0,1,0,0];
    else if (event.target.value === "4")
      dict[event.target.name] = [0,0,0,1,0];
    else if (event.target.value === "5")
      dict[event.target.name] = [0,0,0,0,1];

    if (first2 === "ge")
      dict = setGenQuestionForm(dict);
    else if (first2 === "cs")
      dict = setCsQuestionForm(dict);
    else if (first2 === "ma")
      dict = setMajorQuestionForm(dict);
  }  
  

  useEffect(() => {   

    // Initialize dict for genQuestions
    // ex. {gen1: [0,0,0,0,0]}
    if (genQuestionResponse != null && Object.keys(genQuestionForm).length === 0 && isEvaluated === false){
      let genKey = "gen";
      let genArrValues = [0,0,0,0,0];
      
      for (let i = 0; i < genQuestionResponse.length; i++) {
        let updatedKey = genKey + String(i + 1);
        var dict = genQuestionForm;
        dict[updatedKey] = genArrValues;
        setGenQuestionForm(dict);              
      }         
    } 

    // Initialize dict for csQuestions
    // ex. {cs1: [0,0,0,0,0]}
    if (genQuestionResponse != null 
      && outcomeResponse != null 
      && Object.keys(csQuestionForm).length === 0){

      let csKey = "cs";
      let csArrValues = [0,0,0,0,0];
        
      var csQuestionsPerOutcome;
      for (let i = 1; i <= Object.values(outcomeResponse[0])[2].length; i++) {
        csQuestionsPerOutcome = i;          
      }

      let counterStart = genQuestionResponse.length;
      for (let i = 1; i <= outcomeResponse.length * csQuestionsPerOutcome; i++) {
        let updatedKey = csKey + String(counterStart + 1);  
        let dict = csQuestionForm;
        dict[updatedKey] = csArrValues;
        setCsQuestionForm(dict);   
        counterStart++;         
      }           
    } 

    // Initialize dict for csQuestions
    // ex. {major1: [0,0,0,0,0]}
    if (genQuestionResponse != null 
      && outcomeResponse != null 
      && majorQuestionResponse != null 
      && major != null
      && Object.keys(majorQuestionForm).length === 0){
 
      let majorKey = "major";
      let majorArrValues = [0,0,0,0,0];
        
      let csQuestionsPerOutcome;
      for (let i = 1; i <= Object.values(outcomeResponse[0])[2].length; i++) {
        csQuestionsPerOutcome = i;          
      }

      let numMajorQuestions;
      for (let i = 1; i <= majorQuestionResponse.length; i++) {
        if (Object.values(majorQuestionResponse[i - 1])[2] === major.id){
          for (let j = 1; j <= Object.values(majorQuestionResponse[i - 1])[1].length; j++) {
            numMajorQuestions = j;          
          }
        }   
      }
      
      var counterStart = genQuestionResponse.length + (outcomeResponse.length * csQuestionsPerOutcome);
      for (let i = 1; i <= numMajorQuestions; i++) {
        let updatedKey = majorKey + String(counterStart + 1); 
        let dict = majorQuestionForm;
        dict[updatedKey] = majorArrValues;
        setMajorQuestionForm(dict);   
        counterStart++;         
      }  
    } 

    if (student_in_section != null){
      if (student_in_section.evaluated){
        navigate("/user", {
          state: { username: studentData.user, token: token },
        });
      } else {
        setIsEvaluated(false);
      }
    }
  }, [genQuestionResponse, csQuestionForm, genQuestionForm, majorQuestionForm, majorQuestionResponse, outcomeResponse]);


  // gen questions render
  let genQuestionsRender = <></>

  genQuestionResponse && (isEvaluated === false) ? genQuestionsRender = (
    genQuestionResponse.map((gen_question, index) => (
      <Form.Group key={index} className="mt-5" required controlId="formBasicEmail">
        <Form.Label className="text-dark"><h5>{gen_question.order}) {gen_question.text}</h5></Form.Label>
        {['radio'].map((type) => (
          <div key={`inline-${type}-group-${index}`} className="mb-3 d-flex">
            <Row>
              <Col>
                <Form.Check feedbackType="invalid" inline="true" label="I agree strongly" value="1" onChange={handleChange} name={"gen" + (index + 1)} type={type} id={`inline-${type}-1-group-${index}`} />
              </Col>
              <Col>
                <Form.Check feedbackType="invalid" inline="true" label="I agree moderately" value="2" onChange={handleChange} name={"gen" + (index + 1)} type={type} id={`inline-${type}-2-group-${index}`} />
              </Col>
              <Col>
                <Form.Check feedbackType="invalid" inline="true" label="I am not sure" value="3" onChange={handleChange}name={"gen" + (index + 1)} type={type} id={`inline-${type}-3-group-${index}`} />
              </Col>
              <Col>
                <Form.Check feedbackType="invalid" inline="true" label="I disagree moderately" value="4" onChange={handleChange} name={"gen" + (index + 1)} type={type} id={`inline-${type}-4-group-${index}`} />
              </Col>
              <Col>
                <Form.Check feedbackType="invalid" inline="true" label="I disagree strongly" value="5" onChange={handleChange} name={"gen" + (index + 1)} type={type} id={`inline-${type}-5-group-${index}`} />
              </Col>
              <Col>
                <Form.Label className="evaluation-error-icon" id={"gen" + (index + 1) + "error"} inline="true" name={"check" + index} ><img alt="" src={close}/></Form.Label>
                <Form.Label className="evaluation-check-icon" id={"gen" + (index + 1)} inline="true" name={"check" + index} ><img alt="" src={check}/></Form.Label>
              </Col>
            </Row>
          </div>
        ))}
      </Form.Group>
    ))
  ) : <></>


  // outcomes and csquestions render
  let outcomeCounter = 0;
  let outcomesRender = <></>
  outcomeResponse && genQuestionResponse && (isEvaluated === false) ? outcomesRender = (
    outcomeResponse.map((outcome, index) => (     
      <Form.Group key={index} className="mt-5" controlId="formBasicEmail">
        <Form.Text key={index}><h5 className="text-dark"><u>Outcome {index + 1}:</u> {outcome.heading}</h5></Form.Text>
        {outcome.questions.map((question, i) => (
          <div key={i}>
            <Form.Label>
              <h5 key={i} className="text-dark">
                {index === 0 ? (outcomeCounter = genQuestionResponse.length + i + 1) : outcomeCounter = outcomeCounter + 1}) {question}
              </h5>
            </Form.Label>
            {['radio'].map((type) => (
              <div key={`inline-${type}-group-${outcomeCounter}`} className="mb-3 d-flex">
                <Row>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I agree strongly" value="1" onChange={handleChange} name={"cs" + (outcomeCounter)} type={type} id={`inline-${type}-1-group-${outcomeCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I agree moderately" value="2" onChange={handleChange} name={"cs" + (outcomeCounter)} type={type} id={`inline-${type}-2-group-${outcomeCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I am not sure" value="3" onChange={handleChange}name={"cs" + (outcomeCounter)} type={type} id={`inline-${type}-3-group-${outcomeCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I disagree moderately" value="4" onChange={handleChange} name={"cs" + (outcomeCounter)} type={type} id={`inline-${type}-4-group-${outcomeCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I disagree strongly" value="5" onChange={handleChange} name={"cs" + (outcomeCounter)} type={type} id={`inline-${type}-5-group-${outcomeCounter}`} />
                  </Col>
                  <Col>
                    <Form.Label className="evaluation-error-icon" id={"cs" + (outcomeCounter) + "error"} inline="true" name={"cs-check" + outcomeCounter} ><img alt="" src={close}/></Form.Label>
                    <Form.Label className="evaluation-check-icon" id={"cs" + (outcomeCounter)} inline="true" name={"cs-check" + outcomeCounter} ><img alt="" src={check}/></Form.Label>
                  </Col>
                </Row>
              </div>
            ))}
          </div>
        ))}    
      </Form.Group>
    ))
  ) : <></>


  // outcomes and csquestions render
  let majorCounter = outcomeCounter;
  let majorRender = <></>
  majorQuestionResponse && genQuestionResponse && outcomeResponse && major && (isEvaluated === false) ? majorRender = (
    majorQuestionResponse.map((majorMap, index) => (     
      <Form.Group key={index} className="mt-5" controlId="formBasicEmail">
        { (majorMap.major === major.id) ? majorMap.questions.map((question, i) => (         
          <div key={i}>
            <Form.Label key={i}>
              <h5 key={i} className="text-dark">
                {index === 0 ? (majorCounter = outcomeCounter + i + 1) : majorCounter = majorCounter + 1}) {question}
              </h5>
            </Form.Label>
            {['radio'].map((type) => (
              <div key={`inline-${type}`} className="mb-3 d-flex">
                <Row>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I agree strongly" value="1" onChange={handleChange} name={"major" + (majorCounter)} type={type} id={`inline-${type}-1-group-${majorCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I agree moderately" value="2" onChange={handleChange} name={"major" + (majorCounter)} type={type} id={`inline-${type}-2-group-${majorCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I am not sure" value="3" onChange={handleChange}name={"major" + (majorCounter)} type={type} id={`inline-${type}-3-group-${majorCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I disagree moderately" value="4" onChange={handleChange} name={"major" + (majorCounter)} type={type} id={`inline-${type}-4-group-${majorCounter}`} />
                  </Col>
                  <Col>
                    <Form.Check feedbackType="invalid" inline="true" label="I disagree strongly" value="5" onChange={handleChange} name={"major" + (majorCounter)} type={type} id={`inline-${type}-5-group-${majorCounter}`} />
                  </Col>
                  <Col>
                    <Form.Label className="evaluation-error-icon" id={"major" + (majorCounter) + "error"} inline="true" name={"major-check" + majorCounter} ><img alt="" src={close}/></Form.Label>
                    <Form.Label className="evaluation-check-icon" id={"major" + (majorCounter)} inline="true" name={"major-check" + majorCounter} ><img alt="" src={check}/></Form.Label>
                  </Col>
                </Row>
              </div>
            ))}
          </div>
        )): <></>}    
      </Form.Group>
    ))
  ) : <></>


  // text area render
  let commentRender = <></>
  majorQuestionResponse && genQuestionResponse && outcomeResponse && (isEvaluated === false) ? commentRender = (
    <div>
      <p>Write your comments below (<b>Optional</b>):</p>
      <TextareaCounter id="message" name="message" value={comments} countLimit={250} onChange={handleComment}/>
    </div>
  ) : <></>

  // button render
  let buttonRender = <></>
  majorQuestionResponse && genQuestionResponse && outcomeResponse && (isEvaluated === false) ? buttonRender = (
    <Button className="mt-5 mb-5" variant="primary" type="submit" style={{ background: "#c5960c", color: "black" }}>
            Submit
    </Button>
  ) : <></>

  return (
    <div className="Evaluation">

      <Container className="mt-5 mb-5 shadow-lg p-3 bg-white rounded text-dark cont">
        <Form className="m-5" onSubmit={handleSubmit}>
          <h2 className="mt-4 text-dark"><b>Part A: Survey of Course Delivery</b></h2>
          <hr />
          {genQuestionsRender}

          <br /><br /><h2 className="mt-4"><b>Part B: Survey of Course Outcomes</b></h2>
          <hr />
          {outcomesRender}

          <br /><br /><h2 className="mt-4"><b>Part C: Survey of Major</b></h2>
          <hr />
          {majorRender}
          
          <br /><br /><h2 className="mt-4"><b>Part D: Student Suggestions</b></h2>
          <hr />
          {commentRender}

          <p className="missing-to-evaluate" id="missed">You missed questions: {missingQuestions}</p>

          {buttonRender}
        </Form>
      </Container>
    </div>
  );
}
export default Evaluation;
