import React, { useRef, useState, useEffect, useLayoutEffect } from "react";
import { useTheme } from "@material-ui/core/styles";

import { v4 as uuidv4 } from "uuid";
import {
  ListItemText,
  TextField,
  Drawer,
  Button,
  Paper,
  Grid,
  Tabs,
  InputAdornment,
  Tab,
  ButtonBase,
  Tooltip,
  Select,
  MenuItem,
  Divider,
  Dialog,
  Modal,
  DialogActions,
  DialogTitle,
  InputLabel,
  DialogContent,
  FormControl,
  IconButton,
  Menu,
  Input,
  FormGroup,
  FormControlLabel,
  Typography,
  Checkbox,
  Breadcrumbs,
  CircularProgress,
  Switch,
  Fade,
} from "@material-ui/core";
import { LockOpen as LockOpenIcon } from "@material-ui/icons";

const ITEM_HEIGHT = 55;
const ITEM_PADDING_TOP = 8;
const MenuProps = {
  PaperProps: {
    style: {
      maxHeight: ITEM_HEIGHT * 4.5 + ITEM_PADDING_TOP,
      minWidth: 500,
      maxWidth: 500,
      scrollX: "auto",
    },
  },
  variant: "menu",
  getContentAnchorEl: null,
};

const registeredApps = [
	"gmail",
	"slack",
	"webex",
	"zoho_desk",
	"outlook_graph",
	"outlook_office365",
	"microsoft_teams",
	"microsoft_teams_user_access",
]

const AuthenticationOauth2 = (props) => {
  const {
    saveWorkflow,
    selectedApp,
    workflow,
    selectedAction,
    authenticationType,
    getAppAuthentication,
    appAuthentication,
    setSelectedAction,
    setNewAppAuth,
    setAuthenticationModalOpen,
		isCloud,
  } = props;
  const theme = useTheme();

  //const [update, setUpdate] = React.useState("|")
  const [defaultConfigSet, setDefaultConfigSet] = React.useState(
    authenticationType.client_id !== undefined &&
      authenticationType.client_id !== null &&
      authenticationType.client_id.length > 0 &&
      authenticationType.client_secret !== undefined &&
      authenticationType.client_secret !== null &&
      authenticationType.client_secret.length > 0
  );

  const [clientId, setClientId] = React.useState(
    defaultConfigSet ? authenticationType.client_id : ""
  );
  const [clientSecret, setClientSecret] = React.useState(
    defaultConfigSet ? authenticationType.client_secret : ""
  );
  const [oauthUrl, setOauthUrl] = React.useState("");
  const [buttonClicked, setButtonClicked] = React.useState(false);
  const [selectedScopes, setSelectedScopes] = React.useState([]);
  const [offlineAccess, setOfflineAccess] = React.useState(true);
  const allscopes =
    authenticationType.scope !== undefined ? authenticationType.scope : [];

  const [manuallyConfigure, setManuallyConfigure] = React.useState(
    defaultConfigSet ? false : true
  );
  const [authenticationOption, setAuthenticationOptions] = React.useState({
    app: JSON.parse(JSON.stringify(selectedApp)),
    fields: {},
    label: "",
    usage: [
      {
        workflow_id: workflow.id,
      },
    ],
    id: uuidv4(),
    active: true,
  });

  if (selectedApp.authentication === undefined) {
    return null;
  }

  const handleOauth2Request = (client_id, client_secret, oauth_url, scopes) => {
    setButtonClicked(true);
    console.log("SCOPES: ", scopes);

		client_id = client_id.trim()
		client_secret = client_secret.trim()
		oauth_url = oauth_url.trim()

    var resources = "";
    if (scopes !== undefined && (scopes !== null) & (scopes.length > 0)) {
			if (offlineAccess === true && !scopes.includes("offline_access")) {
				if (authenticationType.redirect_uri.includes("microsoft")) {
					console.log("Appending offline access")
					scopes.push("offline_access")
				}
			}

      resources = scopes.join(" ");
      //resources = scopes.join(",");
    }

    const authentication_url = authenticationType.token_uri;
    //console.log("AUTH: ", authenticationType)
    //console.log("SCOPES2: ", resources)
    const redirectUri = `${window.location.protocol}//${window.location.host}/set_authentication`;
    var state = `workflow_id%3D${workflow.id}%26reference_action_id%3d${selectedAction.app_id}%26app_name%3d${selectedAction.app_name}%26app_id%3d${selectedAction.app_id}%26app_version%3d${selectedAction.app_version}%26authentication_url%3d${authentication_url}%26scope%3d${resources}%26client_id%3d${client_id}%26client_secret%3d${client_secret}`;
    if (oauth_url !== undefined && oauth_url !== null && oauth_url.length > 0) {
      state += `%26oauth_url%3d${oauth_url}`;
      console.log("ADDING OAUTH2 URL: ", state);
    }

    if (
      authenticationType.refresh_uri !== undefined &&
      authenticationType.refresh_uri !== null &&
      authenticationType.refresh_uri.length > 0
    ) {
      state += `%26refresh_uri%3d${authenticationType.refresh_uri}`;
    } else {
      state += `%26refresh_uri%3d${authentication_url}`;
    }

    const url = `${authenticationType.redirect_uri}?client_id=${client_id}&redirect_uri=${redirectUri}&response_type=code&scope=${resources}&prompt=consent&state=${state}&access_type=offline`;

    //const url = `https://accounts.zoho.com/oauth/v2/auth?response_type=code&client_id=${client_id}&scope=AaaServer.profile.Read&redirect_uri=${redirectUri}&prompt=consent`
    //console.log("Full URI: ", url)
    //console.log("Redirect Uri: ", redirectUri)
    // &resource=https%3A%2F%2Fgraph.microsoft.com&

    // FIXME: Awful, but works for prototyping
    // How can we get a callback properly realtime?
    // How can we properly try-catch without breaks on error?
    try {
      var newwin = window.open(url, "", "width=800,height=600");
      //console.log(newwin)

      var open = true;
      const timer = setInterval(() => {
        if (newwin.closed) {
          setButtonClicked(false);
          clearInterval(timer);
          //alert('"Secure Payment" window closed!');

          getAppAuthentication(true, true);
        }
      }, 1000);
      //do {
      //	setTimeout(() => {
      //		console.log(newwin)
      //		console.log("CLOSED", newwin.closed)
      //		if (newwin.closed) {

      //			open = false
      //		}
      //	}, 1000)
      //}
      //while(open === true)
    } catch (e) {
      alert.error(
        "Failed authentication - probably bad credentials. Try again"
      );
      setButtonClicked(false);
    }

    return;
    //do {
    //} while (
  };

  authenticationOption.app.actions = [];

  for (var key in selectedApp.authentication.parameters) {
    if (
      authenticationOption.fields[
        selectedApp.authentication.parameters[key].name
      ] === undefined
    ) {
      authenticationOption.fields[
        selectedApp.authentication.parameters[key].name
      ] = "";
    }
  }

  const handleSubmitCheck = () => {
    console.log("NEW AUTH: ", authenticationOption);
    if (authenticationOption.label.length === 0) {
      authenticationOption.label = `Auth for ${selectedApp.name}`;
      //alert.info("Label can't be empty")
      //return
    }

    // Automatically mapping fields that already exist (predefined).
    // Warning if fields are NOT filled
    for (var key in selectedApp.authentication.parameters) {
      if (
        authenticationOption.fields[
          selectedApp.authentication.parameters[key].name
        ].length === 0
      ) {
        if (
          selectedApp.authentication.parameters[key].value !== undefined &&
          selectedApp.authentication.parameters[key].value !== null &&
          selectedApp.authentication.parameters[key].value.length > 0
        ) {
          authenticationOption.fields[
            selectedApp.authentication.parameters[key].name
          ] = selectedApp.authentication.parameters[key].value;
        } else {
          if (
            selectedApp.authentication.parameters[key].schema.type === "bool"
          ) {
            authenticationOption.fields[
              selectedApp.authentication.parameters[key].name
            ] = "false";
          } else {
            alert.info(
              "Field " +
                selectedApp.authentication.parameters[key].name +
                " can't be empty"
            );
            return;
          }
        }
      }
    }

    console.log("Action: ", selectedAction);
    selectedAction.authentication_id = authenticationOption.id;
    selectedAction.selectedAuthentication = authenticationOption;
    if (
      selectedAction.authentication === undefined ||
      selectedAction.authentication === null
    ) {
      selectedAction.authentication = [authenticationOption];
    } else {
      selectedAction.authentication.push(authenticationOption);
    }

    setSelectedAction(selectedAction);

    var newAuthOption = JSON.parse(JSON.stringify(authenticationOption));
    var newFields = [];
    for (const key in newAuthOption.fields) {
      const value = newAuthOption.fields[key];
      newFields.push({
        key: key,
        value: value,
      });
    }

    console.log("FIELDS: ", newFields);
    newAuthOption.fields = newFields;
    setNewAppAuth(newAuthOption);
    //appAuthentication.push(newAuthOption)
    //setAppAuthentication(appAuthentication)
    //

    //if (configureWorkflowModalOpen) {
    //	setSelectedAction({})
    //}
    //setUpdate(authenticationOption.id)

    /*
			{selectedAction.authentication.map(data => (
			<MenuItem key={data.id} style={{backgroundColor: inputColor, color: "white"}} value={data}>
		*/
  };

  const handleScopeChange = (event) => {
    const {
      target: { value },
    } = event;

    console.log("VALUE: ", value);

    // On autofill we get a the stringified value.
    setSelectedScopes(typeof value === "string" ? value.split(",") : value);
  };

  if (
    authenticationOption.label === null ||
    authenticationOption.label === undefined
  ) {
    authenticationOption.label = selectedApp.name + " authentication";
  }

  //console.log(
  return (
    <div>
      <DialogTitle>
        <div style={{ color: "white" }}>
          Authentication for {selectedApp.name}
        </div>
      </DialogTitle>
      <DialogContent>
        <span style={{}}>
            Oauth2 requires a client ID and secret to authenticate, defined in the remote system. Your redirect URL is <b>https://shuffler.io/set_authentication</b>.
          <a
            target="_blank"
            rel="norefferer"
            href="https://shuffler.io/docs/apps#authentication"
            style={{ textDecoration: "none", color: "#f85a3e" }}
          >
            {" "}
            Learn more about Oauth2 with Shuffle
          </a>
          <div />
        </span>

				{isCloud && registeredApps.includes(selectedApp.name.toLowerCase()) ? 
					<span>
						<Button
							style={{
								marginBottom: 20,
								marginTop: 20,
								borderRadius: theme.palette.borderRadius,
							}}
          		disabled={
            		clientSecret.length > 0 || clientId.length > 0
							}
							variant="contained"
							fullWidth
							onClick={() => {
								// Hardcode some stuff?
								// This could prolly be added to the app itself with a "default" client ID 
								console.log("APP: ", selectedApp)
								if (selectedApp.name.toLowerCase() == "outlook_graph" || selectedApp.name.toLowerCase() == "outlook_office365") {
									handleOauth2Request(
										"efe4c3fe-84a1-4821-a84f-23a6cfe8e72d",
										"",
										"https://graph.microsoft.com",
										["Mail.ReadWrite"],
									);
								} else if (selectedApp.name.toLowerCase() == "gmail") {
									handleOauth2Request(
										"253565968129-c0a35knic7q1pdk6i6qk9gdkvr07ci49.apps.googleusercontent.com",
										"",
										"https://gmail.googleapis.com",
										["https://www.googleapis.com/auth/gmail.modify",
											"https://www.googleapis.com/auth/gmail.send",
											"https://www.googleapis.com/auth/gmail.insert",
											"https://www.googleapis.com/auth/gmail.compose"]
									)
								} else if (selectedApp.name.toLowerCase() == "zoho_desk") {
									handleOauth2Request(
										"1000.ZR5MHUW6B0L6W1VUENFGIATFS0TOJT",
										"",
										"https://desk.zoho.com",
										["Desk.tickets.READ",
										"Desk.tickets.UPDATE",
										"Desk.tickets.DELETE",
										"Desk.tickets.CREATE"]
									)
								} else if (selectedApp.name.toLowerCase() == "slack") {
									handleOauth2Request(
										"151779186901.2448678750935",
										"",
										"https://slack.com",
										["admin", "chat:write", "im:read", "im:write", "search:read", "usergroups:read", "usergroups:write"]
									)
								} else if (selectedApp.name.toLowerCase() == "webex") {
									handleOauth2Request(
										"Cab184f3d7271f540443c79b5b79845e3387abbbdb3db4233a87ea3a5432fb3d5",
										"",
										"https://webexapis.com",
										["spark:all"]
									)
								} else if (selectedApp.name.toLowerCase().includes("microsoft_teams")) {
									handleOauth2Request(
										"31cb4c84-658e-43d5-ae84-22c9142e967a",
										"",
										"https://graph.microsoft.com",
										["ChannelMessage.Edit", "ChannelMessage.Read.All", "ChannelMessage.Send", "Chat.Create", "Chat.ReadWrite", "Chat.Read"]
									)
								}
							}}
							color="primary"
						>
							{buttonClicked ? (
								<CircularProgress style={{ color: "white" }} />
							) : (
								"Auto-authenticate"
							)}
						</Button>
						<Typography style={{textAlign: "center", marginTop: 0, marginBottom: 10, }}>
							OR
						</Typography>
					</span>
				: null}
        {/*<TextField
						style={{backgroundColor: theme.palette.inputColor, borderRadius: theme.palette.borderRadius,}} 
						InputProps={{
							style:{
								color: "white",
								marginLeft: "5px",
								maxWidth: "95%",
								height: 50, 
								fontSize: "1em",
							},
						}}
						fullWidth
						color="primary"
						placeholder={"Auth july 2020"}
						defaultValue={`Auth for ${selectedApp.name}`}
						onChange={(event) => {
							authenticationOption.label = event.target.value
						}}
					/>
				<Divider style={{marginTop: 15, marginBottom: 15, backgroundColor: "rgb(91, 96, 100)"}}/>
				*/}

        {!manuallyConfigure ? null : (
          <span>
            {selectedApp.authentication.parameters.map((data, index) => {
              //console.log(data, index)
              if (data.name === "client_id" || data.name === "client_secret") {
                return null;
              }

              if (data.name !== "url") {
                return null;
              }

              if (oauthUrl.length === 0) {
                setOauthUrl(data.value);
              }

              return (
                <div key={index} style={{ marginTop: 10 }}>
                  <LockOpenIcon style={{ marginRight: 10 }} />
                  <b>{data.name}</b>

                  {data.schema !== undefined &&
                  data.schema !== null &&
                  data.schema.type === "bool" ? (
                    <Select
                      SelectDisplayProps={{
                        style: {
                          marginLeft: 10,
                        },
                      }}
                      defaultValue={"false"}
                      fullWidth
                      onChange={(e) => {
                        console.log("Value: ", e.target.value);
                        authenticationOption.fields[data.name] = e.target.value;
                      }}
                      style={{
                        backgroundColor: theme.palette.surfaceColor,
                        color: "white",
                        height: 50,
                      }}
                    >
                      <MenuItem
                        key={"false"}
                        style={{
                          backgroundColor: theme.palette.inputColor,
                          color: "white",
                        }}
                        value={"false"}
                      >
                        false
                      </MenuItem>
                      <MenuItem
                        key={"true"}
                        style={{
                          backgroundColor: theme.palette.inputColor,
                          color: "white",
                        }}
                        value={"true"}
                      >
                        true
                      </MenuItem>
                    </Select>
                  ) : (
                    <TextField
                      style={{
                        backgroundColor: theme.palette.inputColor,
                        borderRadius: theme.palette.borderRadius,
                      }}
                      InputProps={{
                        style: {
                          color: "white",
                          marginLeft: "5px",
                          maxWidth: "95%",
                          height: 50,
                          fontSize: "1em",
                        },
                      }}
                      fullWidth
                      type={
                        data.example !== undefined &&
                        data.example.includes("***")
                          ? "password"
                          : "text"
                      }
                      color="primary"
                      defaultValue={
                        data.value !== undefined && data.value !== null
                          ? data.value
                          : ""
                      }
                      placeholder={data.example}
                      onChange={(event) => {
                        authenticationOption.fields[data.name] =
                          event.target.value;
                        console.log("Setting oauth url");
                        setOauthUrl(event.target.value);
                        //const [oauthUrl, setOauthUrl] = React.useState("")
                      }}
                    />
                  )}
                </div>
              );
            })}
            <TextField
              style={{
                marginTop: 20,
                backgroundColor: theme.palette.inputColor,
                borderRadius: theme.palette.borderRadius,
              }}
              InputProps={{
                style: {
                  color: "white",
                  marginLeft: "5px",
                  maxWidth: "95%",
                  fontSize: "1em",
                  height: "50px",
                },
              }}
              fullWidth
              color="primary"
              placeholder={"Client ID"}
              onChange={(event) => {
                setClientId(event.target.value);
                //authenticationOption.label = event.target.value
              }}
            />
            <TextField
              style={{
                backgroundColor: theme.palette.inputColor,
                borderRadius: theme.palette.borderRadius,
								marginBottom: 10, 
              }}
              InputProps={{
                style: {
                  color: "white",
                  marginLeft: "5px",
                  maxWidth: "95%",
                  fontSize: "1em",
                  height: "50px",
                },
              }}
              fullWidth
              color="primary"
              placeholder={"Client Secret"}
              onChange={(event) => {
                setClientSecret(event.target.value);
                //authenticationOption.label = event.target.value
              }}
            />
            {allscopes.length === 0 ? null : (
							<div style={{width: "100%", marginTop: 10, display: "flex"}}>
								<span>
									Scopes
									<Select
										multiple
										value={selectedScopes}
										style={{
											backgroundColor: theme.palette.inputColor,
											color: "white",
											padding: 5, 
											minWidth: 300,
											maxWidth: 300,
										}}
										onChange={(e) => {
											handleScopeChange(e)
										}}
										fullWidth
										input={<Input id="select-multiple-native" />}
										renderValue={(selected) => selected.join(", ")}
										MenuProps={MenuProps}
									>
										{allscopes.map((data, index) => {
											return (
												<MenuItem key={index} value={data}>
													<Checkbox checked={selectedScopes.indexOf(data) > -1} />
													<ListItemText primary={data} />
												</MenuItem>
											);
										})}
									</Select>
								</span>
								<span>
									<Tooltip
										color="primary"
										title={"Automatic Refresh (default: true)"}
										placement="top"
									>
										<Checkbox style={{paddingTop: 20}} color="secondary" checked={offlineAccess} onClick={() => {
											setOfflineAccess(!offlineAccess)
										}}/>
									</Tooltip>
								</span>
							</div>
            )}
          </span>
        )}
        <Button
          style={{
            marginBottom: 40,
            marginTop: 20,
            borderRadius: theme.palette.borderRadius,
          }}
          disabled={
            clientSecret.length === 0 || clientId.length === 0 || buttonClicked || selectedScopes.length === 0
          }
          variant="contained"
          fullWidth
          onClick={() => {
            handleOauth2Request(
              clientId,
              clientSecret,
              oauthUrl,
              selectedScopes
            );
          }}
          color="primary"
        >
          {buttonClicked ? (
            <CircularProgress style={{ color: "white" }} />
          ) : (
            "Manually Authenticate"
          )}
        </Button>



        {defaultConfigSet ? (
          <span style={{}}>
            ... or
            <Button
              style={{
                marginLeft: 10,
                borderRadius: theme.palette.borderRadius,
              }}
              disabled={clientSecret.length === 0 || clientId.length === 0}
              variant="text"
              onClick={() => {
                setManuallyConfigure(!manuallyConfigure);

                if (manuallyConfigure) {
                  setClientId(authenticationType.client_id);
                  setClientSecret(authenticationType.client_secret);
                } else {
                  setClientId("");
                  setClientSecret("");
                }
              }}
              color="primary"
            >
              {manuallyConfigure
                ? "Use auto-config"
                : "Manually configure Oauth2"}
            </Button>
          </span>
        ) : null}
      </DialogContent>
    </div>
  );
};

export default AuthenticationOauth2;
