// pages/index.tsx
import Head from 'next/head';
import { useEffect, useRef, useState } from 'react';

import Box from '../../components/Box';
import TextArea from '../../components/TextArea';
import Input from '../../components/Input';
import Button from '../../components/Button';
import Markdown from '../../components/Markdown';
import Typography from '../../components/Typography';

import Script from 'next/script';

// @ts-ignore
import desc from './desc.md';


/*
 * HOOK THE MODULE FROM THE DOM
 */

declare global {
  interface Window {
    Module: any;
  }
}

const useModule = <T extends any>(onInitCallback? : (module: T) => void): T | null => {
  const [module, setModule] = useState<T | null>(null);

  useEffect(() => {

    var Module = {
      onRuntimeInitialized: function () {
        if(onInitCallback !== undefined) {
          onInitCallback(window.Module);
        }

        setModule(window.Module);
      },
    };

    if(module === null && typeof window.Module === "object") {
      if(onInitCallback !== undefined) {
        onInitCallback(window.Module);
      }

      setModule(window.Module);
    }

  });


  return module;
};


const DEMO_CONFIG = `[Interface]
PrivateKey = 0OCS+dV5wsDje6qUAEDQzPmTNWOLE9HE8kfGU1wJUE0=
Address = 10.55.127.342/32, ab00:aaaa:aaa:aa02::5:abcd/128
DNS = 10.64.0.1

[Peer]
PublicKey = WBSnuq6Vswxz5G5zz9pUt60ZSA+JfZ1iTXdg0RJGjks=
AllowedIPs = 0.0.0.0/0,::0/0
Endpoint = 128.45.210.64:51821
`;

let rows = 0;
for(const char of DEMO_CONFIG)
  if(char == '\n') rows++;

interface PanelProps {
  children?: React.ReactNode;
  customStyle?: React.CSSProperties;
};

const Panel: React.FC<PanelProps> = ({ children, customStyle }) => (
    <section style={{
      backgroundColor: '#f8f9fa',
      marginTop: '1.5rem',
      padding: '1.5rem',
      ...customStyle
    }}>
      {children}
    </section>
);

interface Wg2ndModule {
  wg2nd_cmdseq: (intfName : string, intfconfig : string) => string;
};

import { Breadcrumbs, LinkCrumb } from "../../components/Breadcrumbs";

const Wg2nd = () => {
  const intfNameRef = useRef<HTMLInputElement>(null);
  const intfConfigRef = useRef<HTMLTextAreaElement>(null);
  const ndConfigRef = useRef<HTMLTextAreaElement>(null);
  const parentDebounceDiv = useRef<HTMLDivElement>(null);

  const convertConfig = (module : Wg2ndModule | null) => {
    if(intfNameRef.current === null || intfConfigRef.current === null || module === null)
      return;

    const intfName = intfNameRef.current!.value;
    const intfConfig = intfConfigRef.current!.value;

    console.log(module);
    const result = module.wg2nd_cmdseq(intfName, intfConfig);

    // This is a hack: adjust a wrapper around the output text area
    // Thus, we can detect the scrollHeight of the TextArea without
    // the screen moving.
    parentDebounceDiv.current!.style.height = ndConfigRef.current!.style.height;
    ndConfigRef.current!.style.height = `0px`;

    ndConfigRef.current!.value = result;

    const scrollHeight = ndConfigRef.current!.scrollHeight;
    ndConfigRef.current!.style.height = `${scrollHeight}px`;
    parentDebounceDiv.current!.style.height = 'auto';
  };

  const module = useModule<Wg2ndModule>(convertConfig);

  return (
  <>
    <script src="/wg2nd/wg2nd_bindings.js" />
    <main
        style={{
            maxWidth: '1200px',
            margin: 'auto',
        }}
    >
      {/* Description */}
      <Panel>
        <Breadcrumbs>
          <LinkCrumb href="/">furkistan.com</LinkCrumb>
          <LinkCrumb href="/wg2nd">wg2nd</LinkCrumb>
        </Breadcrumbs>

        <Markdown md={desc} />
      </Panel>

      {/* Input Panel */}
      <Panel>
        <Typography variant="h3">WireGuard Configuration</Typography>
        <Box my={1}>
          <label htmlFor="wg_config_intf_name">
            <Typography variant="h4" gutter>Interface Name</Typography>
          </label>
          <Input
            ref={intfNameRef}
            id="wg_config_intf_name"
            defaultValue="wg0"
            spellCheck={false}
          />
        </Box>
        <Box my={1}>
          <label htmlFor="wg_config_conf">
            <Typography variant="h4" gutter>Interface Configuration</Typography>
          </label>
          <TextArea
            ref={intfConfigRef}
            id="wg_config_conf"
            defaultValue={DEMO_CONFIG}
            rows={rows}
            spellCheck={false}
          />
        </Box>
        <Button
          sx={{width: '100%'}}
          onClick={(e) => { convertConfig(module); }}
        >Generate</Button>
      </Panel>

      {/* Output Panel */}
      <Panel>
        <label htmlFor="nd_config_cmds">
          <Typography variant="h3">Networkd Configuration</Typography>
        </label>
        <Box my={1}>
          <div ref={parentDebounceDiv} >
            <TextArea
              sx={{ overflowY: 'hidden' }}
              id="nd_config_cmds"
              ref={ndConfigRef}
              spellCheck={false}
              readOnly
            />
          </div>
        </Box>
      </Panel>
    </main>
  </>
  );
};

export default Wg2nd;
