import styled from "styled-components";
import Button from "@material-ui/core/Button";
import Input from "@material-ui/core/Input";
import InputLabel from "@material-ui/core/InputLabel";
import InputAdornment from "@material-ui/core/InputAdornment";
import FormControl from "@material-ui/core/FormControl";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";
import Section, { SectionLabel } from "../common/FormSection";
import { fromBigNumber, toBigNumber } from "../common/utils";
import BZxComponent from "../common/BZxComponent";

const Container = styled.div`
  width: 100%;
  text-align: left;
`;

const StyledDiv = styled.div`
  margin: 0;
  display: block;
  color: rgba(0, 0, 0, 0.87);
  font-size: 0.875rem;
  font-weight: 400;
  font-family: "Raleway", sans-serif;
  line-height: 1.46429em;
  margin-bottom: 0.35em;
`;

const ButtonGroup = styled.div`
  margin-left: auto;
  display: flex;
  align-items: center;

  & > *:first-child {
    margin-right: 12px;
  }
`;

const TxHashLink = styled.a.attrs({
  target: `_blank`,
  rel: `noopener noreferrer`
})`
  font-family: monospace;
  display: block;
  text-overflow: ellipsis;
  overflow: auto;
}
`;

export default class Ether extends BZxComponent {
  state = {
    ethBalance: null,
    wethBalance: null,
    showWrapDialog: false,
    showUnWrapDialog: false,
    wrapAmount: ``
  };

  async componentDidMount() {
    await this.updateBalances();
  }

  async componentDidUpdate(prevProps) {
    if (
      prevProps.lastTokenRefresh &&
      prevProps.lastTokenRefresh !== this.props.lastTokenRefresh
    )
      await this.updateBalances();
  }

  getWethBalance = async () => {
    const { bZx, tokens, accounts } = this.props;
    const token = await tokens.filter(t => t.symbol === `WETH`)[0];
    
    const balance = await this.wrapAndRun(bZx.getBalance({
      tokenAddress: token.address,
      ownerAddress: accounts[0].toLowerCase()
    }));
    console.log(`balance of`, token.name, balance.toNumber());
    this.setState({ wethBalance: fromBigNumber(balance, 1e18) });
  };

  setWrapAmount = e => this.setState({ wrapAmount: e.target.value });

  updateBalances = async () => {
    const { web3, accounts } = this.props;
    const balanceInWei = await this.wrapAndRun(web3.eth.getBalance(accounts[0]));
    await this.getWethBalance();
    this.setState({ ethBalance: balanceInWei / 1e18 });
  };

  toggleWrapDialog = () =>
    this.setState(p => ({ showWrapDialog: !p.showWrapDialog }));

  toggleUnWrapDialog = () =>
    this.setState(p => ({ showUnWrapDialog: !p.showUnWrapDialog }));

  wrapEth = async () => {
    const { web3, bZx, accounts } = this.props;
    const { wrapAmount } = this.state;

    if (bZx.portalProviderName !== `MetaMask`) {
      alert(`Please confirm this transaction on your device.`);
    }

    const txOpts = {
      from: accounts[0],
      gas: 2000000,
      gasPrice: window.defaultGasPrice.toString(),
      value: toBigNumber(wrapAmount, 1e18)
    };

    const txObj = await bZx.wrapEth({
      amount: toBigNumber(wrapAmount, 1e18),
      getObject: true,
      txOpts
    });

    try {
      await txObj
        .estimateGas(txOpts)
        .then(gas => {
          console.log(gas);
          txOpts.gas = window.gasValue(gas)+10000; // WETH deposit gas estimate seems to often be under
          txObj
            .send(txOpts)
            .once(`transactionHash`, hash => {
              alert(`Transaction submitted, transaction hash:`, {
                component: () => (
                  <TxHashLink href={`${bZx.etherscanURL}tx/${hash}`}>
                    {hash}
                  </TxHashLink>
                )
              });
              this.setState({ wrapAmount: ``, showWrapDialog: false });
            })
            .then(async () => {
              alert(`Your ether is wrapped.`);
              const balanceInWei = await web3.eth.getBalance(accounts[0]);
              await this.setState({ ethBalance: balanceInWei / 1e18 });
              await this.props.updateTrackedTokens(true);
            })
            .catch(error => {
              console.error(error.message);
              if (
                error.message.includes(`denied transaction signature`) ||
                error.message.includes(`Condition of use not satisfied`) ||
                error.message.includes(`Invalid status`)
              ) {
                alert();
              }
              this.setState({ wrapAmount: ``, showWrapDialog: false });
            });
        })
        .catch(error => {
          console.error(error.message);
          if (
            error.message.includes(`denied transaction signature`) ||
            error.message.includes(`Condition of use not satisfied`) ||
            error.message.includes(`Invalid status`)
          ) {
            alert();
          }
          this.setState({ wrapAmount: ``, showWrapDialog: false });
        });
    } catch (error) {
      console.error(error.message);
      if (
        error.message.includes(`denied transaction signature`) ||
        error.message.includes(`Condition of use not satisfied`) ||
        error.message.includes(`Invalid status`)
      ) {
        alert();
      }
      this.setState({ wrapAmount: ``, showWrapDialog: false });
    }
  };

  unwrapEth = async () => {
    const { web3, bZx, accounts } = this.props;
    const { wrapAmount } = this.state;

    if (bZx.portalProviderName !== `MetaMask`) {
      alert(`Please confirm this transaction on your device.`);
    }

    const txOpts = {
      from: accounts[0],
      // gas: 1000000,
      gasPrice: window.defaultGasPrice.toString()
    };

    const txObj = await bZx.unwrapEth({
      amount: toBigNumber(wrapAmount, 1e18),
      getObject: true,
      txOpts
    });

    try {
      await txObj
        .estimateGas(txOpts)
        .then(gas => {
          console.log(gas);
          txOpts.gas = window.gasValue(gas);
          txObj
            .send(txOpts)
            .once(`transactionHash`, hash => {
              alert(`Transaction submitted, transaction hash:`, {
                component: () => (
                  <TxHashLink href={`${bZx.etherscanURL}tx/${hash}`}>
                    {hash}
                  </TxHashLink>
                )
              });
              this.setState({ wrapAmount: ``, showUnWrapDialog: false });
            })
            .then(async () => {
              alert(`Your ether is unwrapped.`);
              const balanceInWei = await web3.eth.getBalance(accounts[0]);
              await this.setState({ ethBalance: balanceInWei / 1e18 });
              await this.props.updateTrackedTokens(true);
            })
            .catch(error => {
              console.error(error.message);
              if (
                error.message.includes(`denied transaction signature`) ||
                error.message.includes(`Condition of use not satisfied`) ||
                error.message.includes(`Invalid status`)
              ) {
                alert();
              }
              this.setState({ wrapAmount: ``, showUnWrapDialog: false });
            });
        })
        .catch(error => {
          console.error(error.message);
          if (
            error.message.includes(`denied transaction signature`) ||
            error.message.includes(`Condition of use not satisfied`) ||
            error.message.includes(`Invalid status`)
          ) {
            alert();
          }
          this.setState({ wrapAmount: ``, showUnWrapDialog: false });
        });
    } catch (error) {
      console.error(error.message);
      if (
        error.message.includes(`denied transaction signature`) ||
        error.message.includes(`Condition of use not satisfied`) ||
        error.message.includes(`Invalid status`)
      ) {
        alert();
      }
      this.setState({ wrapAmount: ``, showUnWrapDialog: false });
    }
  };

  render() {
    return (
      <Section>
        <SectionLabel>ETH to WETH</SectionLabel>
        <Container>
          {this.state.ethBalance != null ? (
            <StyledDiv>
              Your current ETH balance is
              {` `}
              <strong>{this.state.ethBalance.toString()} ETH</strong>.
            </StyledDiv>
          ) : (
            <StyledDiv>
              Your current Ether balance is <strong>loading...</strong>.
            </StyledDiv>
          )}
          {this.state.wethBalance != null ? (
            <StyledDiv>
              Your current WETH balance is
              {` `}
              <strong>{this.state.wethBalance.toString()} WETH</strong>.
            </StyledDiv>
          ) : (
            <StyledDiv>
              Your current WETH balance is <strong>loading...</strong>.
            </StyledDiv>
          )}
          <br />
          <StyledDiv>
            You will need to WRAP your ETH to {` `}
            <a
              href="https://weth.io/"
              target="_blank"
              rel="noreferrer noopener"
            >
              WETH
            </a>
            {` `}
            to use it with bZx.
            <br />
            You can UNWRAP your WETH at anytime to get your ETH back.
          </StyledDiv>
          <br />
          <StyledDiv>
            <ButtonGroup>
              <Button
                variant="raised"
                color="primary"
                onClick={this.toggleWrapDialog}
                style={{ marginLeft: `12px` }}
              >
                Wrap ETH
              </Button>
              <Button
                variant="raised"
                color="primary"
                onClick={this.toggleUnWrapDialog}
                style={{ marginLeft: `12px` }}
              >
                UnWrap ETH
              </Button>
            </ButtonGroup>
          </StyledDiv>
          <Dialog
            open={this.state.showWrapDialog}
            onClose={this.toggleWrapDialog}
          >
            <DialogTitle>Wrap ETH</DialogTitle>
            <DialogContent>
              <DialogContentText>
                This will wrap ETH into the WETH token. Please specify the the
                amount of Ether you want to wrap.
              </DialogContentText>
              <FormControl fullWidth>
                <InputLabel>Wrap Amount</InputLabel>
                <Input
                  value={this.state.wrapAmount}
                  type="number"
                  onChange={this.setWrapAmount}
                  endAdornment={
                    <InputAdornment position="end">ETH</InputAdornment>
                  }
                />
              </FormControl>
            </DialogContent>
            <DialogActions>
              <Button onClick={this.toggleWrapDialog}>Cancel</Button>
              <Button onClick={this.wrapEth} color="primary">
                Wrap
              </Button>
            </DialogActions>
          </Dialog>
          <Dialog
            open={this.state.showUnWrapDialog}
            onClose={this.toggleUnWrapDialog}
          >
            <DialogTitle>Unwrap ETH</DialogTitle>
            <DialogContent>
              <DialogContentText>
                This will unwrap ETH from the WETH token. Please specify the the
                amount of WETH you want to unwrap.
              </DialogContentText>
              <FormControl fullWidth>
                <InputLabel>Unwrap Amount</InputLabel>
                <Input
                  value={this.state.wrapAmount}
                  type="number"
                  onChange={this.setWrapAmount}
                  endAdornment={
                    <InputAdornment position="end">WETH</InputAdornment>
                  }
                />
              </FormControl>
            </DialogContent>
            <DialogActions>
              <Button onClick={this.toggleUnWrapDialog}>Cancel</Button>
              <Button onClick={this.unwrapEth} color="primary">
                Unwrap
              </Button>
            </DialogActions>
          </Dialog>
        </Container>
      </Section>
    );
  }
}
