import React, { Component } from "react";
import TopHeader from "../components/top_header";
import BottomHeader from "../components/bottom_header";
import TokenHeader from "../containers/token_header";
import { addToken, setCurrentToken, setURL } from "../actions/index";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { Token } from "../libraries";
import { HashLoader } from "react-spinners";
import web3 from "../web3";
import URLFactory from "../factory";
import abi from "../url";

const createContract = async url => {
  const accounts = await web3.eth.getAccounts();
  await URLFactory.methods.createURLToken(url).send({ from: accounts[0] });
  const addresses = await URLFactory.methods.getDeployedURL().call();
  const urlTokenAddress = addresses[addresses.length - 1];
  const urlTokenABI = abi;

  const URLToken = await new web3.eth.Contract(urlTokenABI, urlTokenAddress);
  return URLToken;
};

// Starting Page
class LandingPage extends Component {
  // Constructor function sets up the initializer for the the entire class.
  constructor(props) {
    super(props);

    // All the components peices of state -- this is used to check if the original landing page should
    //display or if the page showing the token should dsiplay -- It is set to false once the user presses the Mint button.
    this.state = {
      onLandingPage: true,
      minting: false
    };
  }

  // Sets the new state of the Landing Page and rerender the entire component.
  async onButtonPress() {
    if (this.props.url !== "") {
      this.setState({ minting: true });
      const contract = await createContract(this.props.url).catch(err => {
        console.log(err);
      });
      if (contract !== undefined) {
        const address = await contract._address;
        const url = await contract.methods.getURL().call();
        const URLToken = new Token(url, address);

        // const result = await deploy(this.props.url);
        // console.log("Result: ", result);
        this.props.addToken(URLToken);
        this.props.setCurrentToken(URLToken);

        this.setState({ onLandingPage: false, minting: false });
      } else {
        this.setState({ minting: false });
      }
      //console.log("URL To Mint: ", this.props.url);
    }
  }

  renderLoadingBar() {
    if (this.state.minting) {
      return (
        <div className="loading-container">
          <div className="loading">
            <HashLoader color={"#ffc66b"} />
            <p className="loading-text">Minting Your URL</p>
          </div>
        </div>
      );
    }
  }

  // If the user is currently on the landing page and hasn't minted a url the main screen will render.
  renderLandingPageHeader() {
    if (this.state.onLandingPage) {
      return (
        <div>
          <TopHeader />
          <BottomHeader
            onButtonPress={this.onButtonPress.bind(this)}
            placeholderText={"Paste your url here..."}
          />
        </div>
      );
    }
  }

  // Once the user submits a url to mint the token page will render -- Pressing the Mint button triggers this to render.
  renderTokenHeader() {
    if (!this.state.onLandingPage) {
      return <TokenHeader onButtonPress={this.onButtonPress.bind(this)} />;
    }
  }

  // This part is what actually renders everything onto the screen. Everytime we do a this.setState() it automatically
  // calls the render function and rerenders any parts of the screen that were changed.
  render() {
    return (
      <div className="main-container">
        {this.renderLoadingBar()}
        {this.renderLandingPageHeader()}
        {this.renderTokenHeader()}
      </div>
    );
  }
}

// This function is used so the current container (landing_page) can connect to Redux and grab the application state we need.
// In this case we specify that we need the url state from the redux store.
// Once we get the state it is passed back to us as properties of the class instead of component state.
function mapStateToProps(state) {
  return {
    url: state.url,
    tokens: state.tokens
  };
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators(
    { addToken: addToken, setURL: setURL, setCurrentToken: setCurrentToken },
    dispatch
  );
}

// On the export is where we actually connect the container to the redux store which can be found in the index.js file
// in the reducers folder
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LandingPage);
