import React from "react";

// 4.2. Go to class LoginButton. In its render() function, we are rendering a login button with the
// handler function this.handleClick bound to the onclick event. Implement the function
// handleClick(): If the input username and password are valid, use
// this.props.handleStatusChange(xx, yy) received from class Lab7App to update the state
// variables of Lab7App, where xx equals “true” and yy equals this.props.username received from
// class Lab7App; otherwise, alert the message “Login failed!” Hint: you can use the provided
// function checkValid() to check if the input username and password are valid, which returns true
// if the inputs are included in the predefined array userDB, and returns false, otherwise. Read more
// about the array find() function at https://developer.mozilla.org/en-
// US/docs/Web/JavaScript/Reference/Global_Objects/Array/find

class LoginButton extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
    this.checkValid = this.checkValid.bind(this);
  }

  checkValid() {
    let item = userDB.find((item) => {
      return item.username == this.props.username && item.password == this.props.password;
    });
    if (item != undefined) return true;
    else return false;
  }

  // step 4.2
  handleClick() {
    if (this.checkValid()) {
      this.props.handleStatusChange(true, this.props.username);
    } else {
      // otherwise, alert the message “Login failed!”
      alert("Login failed!");
    }
  }

  render() {
    return <button onClick={() => this.handleClick()}>Login</button>;
  }
}

class Contents extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      topics: topicsDB,
    };
    this.handleTopicsChange = this.handleTopicsChange.bind(this);
  }

  // step 7
  // Step 7. Implement filtering of topics list
  // Now implement the function handleTopicsChange() in class Contents as follows: if value of the
  // argument option is not “all” (i.e., it is one of the three sections instead), apply filter() function on
  // topicsDB to obtain a filtered topics array where each topic’s section is option (learn more about
  // JavaScript Array filter method at https://developer.mozilla.org/en-
  // US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), and set the state variable
  // Topics to be the filtered array; otherwise, set the state variable Topics to be topicsDB. Note that
  // you need to use this.setState() to change a state variable’s value.
  handleTopicsChange(option) {
    if (option == "all") {
      this.setState({ topics: topicsDB });
    } else {
      this.setState({ topics: topicsDB.filter((o) => o.section == option) });
    }
  }

  render() {
    const topics = this.state.topics;
    return (
      <div id="contents">
        <DropDownList handleTopicsChange={this.handleTopicsChange} />
        {
          // Step 5. Render topics list in class component Contents
          // Go to class Contents, which has a state of one key-value pair: topics stores the list of topics to be
          // shown on the page, initialized using the given array topicsDB. Complete the render() function of
          // class Contents: within { }, apply map() function on topics to create a number of <p> elements,
          // each presenting information of one topic in the topics array as <p>Section: {topic.section}; Topic
          // Name: {topic.topic}</p>. The handler function handleTopicsChange() is to change the state
          // variable topics upon selecting a different option in the drop-down list (to be implemented later).

          topics.map((topic) => {
            return (
              <>
                <p>
                  Section: {topic.section}; Name: {topic.topic}
                </p>
              </>
            );
          })
        }
      </div>
    );
  }
}

function DropDownList(props) {
  var key_pool = {};
  const getUniq = (value_in) => {
    if (key_pool[value_in] != undefined) return false;

    key_pool[value_in] = "";
    return true;
  };
  return (
    <div>
      <b>Choose one section: </b>

      {
        // Step 6. Render a drop-down list in function component DropDownList
        // Now go to function DropDownList, which receives the handler function handleTopicsChange of
        // class Contents in its props. Complete its render() function as follows: remove "{/* step 6*/}", and
        // in its place, create a drop-down list using the <select> element with four options (with values
        // “all”, “section-1”, “section-2” and “section-3”, respectively). The option “all” should be
        // associated with the attribute “selected” as the default option. Add an event handler function to
        // onChange event on the <select> element (to track the change of selected option and update
        // topics list accordingly), which should be e => props.handleTopicsChange(e.target.value).
      }
      <></>
      {
        <select onChange={(e) => props.handleTopicsChange(e.target.value)}>
          <option selected value="all">
            all
          </option>
          {
            // topicsDB
            //  get unique by section
            //  extract section
            //  sort before exit
          }
          {topicsDB
            .filter((t) => getUniq(t.section))
            .map((ut) => ut.section)
            .sort()
            .map((ts) => (
              <option value={ts}>{ts}</option>
            ))}
        </select>
      }
    </div>
  );
}

class Lab7App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isLogin: false,
      loginName: "",
      inputUserName: "",
      inputUserPswd: "",
    };
    this.handleInputChange = this.handleInputChange.bind(this);
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  // step 3
  handleInputChange(event) {
    let target = event.target;
    let name = target.name;
    let value = target.value;
    this.setState({ [name]: value });
  }

  handleStatusChange(newStatus, loginName) {
    const isUserLoggedIn = (login_status) => login_status == true;

    if (isUserLoggedIn(newStatus)) {
      this.setState({ isLogin: newStatus, loginName: loginName });
    } else {
      this.setState({ isLogin: newStatus, loginName: loginName, inputUserName: "", inputUserPswd: "" });
    }
  }

  render() {
    if (!this.state.isLogin) {
      return (
        <div>
          <p>Fill in username and password and click the button to log in</p>
          <input type="text" name="inputUserName" placeholder="username" value={this.state.inputUserName} onChange={(e) => this.handleInputChange(e)} />
          <input type="password" name="inputUserPswd" placeholder="password" value={this.state.inputUserPswd} onChange={(e) => this.handleInputChange(e)} />

          {
            // 4.1. In the render() function of Lab7App, render the
            //   LoginButton component. The LoginButton component receives three props:
            //   1. username: which equals the value of state variable inputUserName;
            //   2. password: which equals the value of state variable inputUserPswd;
            //   3. handleStatusChange: which equals this.handleStatusChange. We have provided the
            //   implementation of function handleStatusChange(), which receives the login status (boolean
            //   type) and the name of the logged-in user (string type) as arguments, and set the state
            //   variables isLogin and loginName to the argument values, respectively. 
          }

          <LoginButton username={this.state.inputUserName} password={this.state.inputUserPswd} handleStatusChange={this.handleStatusChange} />
        </div>
      );
    } else {
      return (
        <div>
          <p>Welcome {this.state.loginName}!</p>
          <button onClick={() => this.handleStatusChange(false, "")}>Logout</button>
          {/* 4.3. Go to class Lab7App. In the render() function, add an onClick event handler to the logout button, which is an
          arrow function ()=>this.handleStatusChange() where handleStatusChange() receives a “false” value and an empty string as arguments. */}
          <Contents />
        </div>
      );
    }
  }
}

const userDB = [
  { username: "Alex", password: "123" },
  { username: "Bob", password: "231" },
  { username: "Jack", password: "321" },
];

const topicsDB = [
  { section: "section-1", topic: "CSS" },
  { section: "section-1", topic: "HTML" },
  { section: "section-1", topic: "WWW" },
  { section: "section-2", topic: "JaveScript" },
  { section: "section-2", topic: "MongoDB" },
  { section: "section-2", topic: "NodeJS" },
  { section: "section-3", topic: "JQuery" },
  { section: "section-3", topic: "React" },
  { section: "section-3", topic: "Vue" },
];

export default Lab7App;
