import styled from '@emotion/styled';
import { Button, Grid, Select, Slider, Tabs, Textarea, TextInput } from "@mantine/core";
import { useMediaQuery } from '@mantine/hooks';
import { useEffect, useState } from 'react';
import { defaultSystemPrompt } from '../openai';
import { defaultVoiceList, getVoices } from '../elevenlabs';
import { useAppContext } from '../context';

const Container = styled.div`
    padding: .4rem 1rem 1rem 1rem;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    max-width: 100vw;
    max-height: 100vh;

    @media (max-width: 40em) {
        padding: 0;
    }

    .mantine-Tabs-root {
        display: flex;
        flex-direction: column;
        height: calc(100% - 3rem);
        
        @media (max-width: 40em) {
            height: calc(100% - 5rem);
        }
    }

    .mantine-Tabs-tab {
        padding: 1.2rem 1.618rem 0.8rem 1.618rem;

        @media (max-width: 40em) {
            padding: 1rem;
            span {
                display: none;
            }
        }
    }

    .mantine-Tabs-panel {
        flex-grow: 1;
        overflow-y: scroll;
        overflow-x: hidden;
        min-height: 0;
        margin-left: 0;
        padding: 1.2rem 0 3rem 0;

        @media (max-width: 40em) {
            padding: 1.2rem 1rem 3rem 1rem;
        }
    }

    #save {
        position: absolute;
        bottom: 0;
        left: 0;
        right: 0;
        padding: 0 1rem 1rem 1rem;
        opacity: 1;

        .mantine-Button-root {
            height: 3rem;
        }
    }
`;

const Settings = styled.div`
    font-family: "Work Sans", sans-serif;
    color: white;

    section {
        margin-bottom: .618rem;
        padding: 0.618rem;

        h3 {
            font-size: 1rem;
            font-weight: bold;
            margin-bottom: 1rem;
        }

        p {
            line-height: 1.7;
            margin-top: 0.8rem;
            font-size: 1rem;
        }

        a {
            color: white;
            text-decoration : underline;
        }

        code {
            font-family: "Fira Code", monospace;
        }
    }
 
    .focused {
        border: thin solid rgba(255, 255, 255, 0.1);
        border-radius: 0.25rem;
        animation: flash 3s;
    }

    @keyframes flash {
        0% {
            border-color: rgba(255, 0, 0, 0);
        }
        50% {
            border-color: rgba(255, 0, 0, 1);
        }
        100% {
            border-color: rgba(255, 255, 255, .1);
        }
    }
`;

export interface SettingsScreenProps {
    parameters: any;
    setParameters: (parameters: any) => any;
}

export default function SettingsScreen(props: SettingsScreenProps) {
    const context = useAppContext();
    const small = useMediaQuery('(max-width: 40em)');
    const { parameters, setParameters } = props;

    const [voices, setVoices] = useState<any[]>(defaultVoiceList);
    useEffect(() => {
        if (context.apiKeys.elevenlabs) {
            getVoices().then(data => {
                if (data?.voices?.length) {
                    setVoices(data.voices);
                }
            });
        }
    }, [context.apiKeys.elevenlabs]);

    if (!context.settings.tab) {
        return null;
    }

    return (
        <Container>
            <Tabs defaultValue={context.settings.tab} style={{ margin: '0rem' }}>
                <Tabs.List grow={small}>
                    <Tabs.Tab value="options">Options</Tabs.Tab>
                    <Tabs.Tab value="user">User</Tabs.Tab>
                    <Tabs.Tab value="speech">Speech</Tabs.Tab>
                </Tabs.List>

                <Tabs.Panel value="user">
                    <Settings>
                        <Grid style={{ marginBottom: '1.618rem' }} gutter={24}>
                            <Grid.Col span={12}>
                                <section className={context.settings.option === 'openai-api-key' ? 'focused' : ''}>
                                    <h3>Your OpenAI API Key</h3>
                                    <TextInput
                                        placeholder="Paste your API key here"
                                        value={context.apiKeys.openai || ''}
                                        onChange={event => {
                                            setParameters({ ...parameters, apiKey: event.currentTarget.value });
                                            context.apiKeys.setOpenAIApiKey(event.currentTarget.value);
                                        }} />
                                    <p><a href="https://platform.openai.com/account/api-keys" target="_blank">Find your API key here.</a> Your API key is stored only on this device and never transmitted to anyone except OpenAI.</p>
                                    <p>OpenAI API key usage is billed at a pay-as-you-go rate, separate from your ChatGPT subscription.</p>
                                </section>
                            </Grid.Col>
                        </Grid>
                    </Settings>
                </Tabs.Panel>

                <Tabs.Panel value="options">
                    <Settings>
                        <Grid style={{ marginBottom: '1.618rem' }} gutter={24}>
                            <Grid.Col span={12}>
                                <section className={context.settings.option === 'system-prompt' ? 'focused' : ''}>
                                    <h3>System Prompt</h3>
                                    <Textarea
                                        value={parameters.initialSystemPrompt || defaultSystemPrompt}
                                        onChange={event => setParameters({ ...parameters, initialSystemPrompt: event.currentTarget.value })}
                                        minRows={5}
                                        maxRows={10}
                                        autosize />
                                    <p style={{ marginBottom: '0.7rem' }}>The System Prompt is shown to ChatGPT by the "System" before your first message. The <code style={{ whiteSpace: 'nowrap' }}>{'{{ datetime }}'}</code> tag is automatically replaced by the current date and time.</p>
                                    {(parameters.initialSystemPrompt?.trim() !== defaultSystemPrompt) && <Button size="xs" compact variant="light" onClick={() => setParameters({ ...parameters, initialSystemPrompt: defaultSystemPrompt })}>
                                        Reset to default
                                    </Button>}
                                </section>
                            </Grid.Col>
                            <Grid.Col span={12}>
                                <section className={context.settings.option === 'temperature' ? 'focused' : ''}>
                                    <h3>Temperature ({parameters.temperature.toFixed(1)})</h3>
                                    <Slider value={parameters.temperature} onChange={value => setParameters({ ...parameters, temperature: value })} step={0.1} min={0} max={1} precision={3} />
                                    <p>The temperature parameter controls the randomness of the AI's responses. Lower values will make the AI more predictable, while higher values will make it more creative.</p>
                                </section>
                            </Grid.Col>
                        </Grid>
                    </Settings>
                </Tabs.Panel>

                <Tabs.Panel value="speech">
                    <Settings>
                        <Grid style={{ marginBottom: '1.618rem' }} gutter={24}>
                            <Grid.Col span={12}>
                                <section className={context.settings.option === 'elevenlabs-api-key' ? 'focused' : ''}>
                                    <h3>Your ElevenLabs Text-to-Speech API Key (optional)</h3>
                                    <TextInput placeholder="Paste your API key here" value={context.apiKeys.elevenlabs || ''} onChange={event => context.apiKeys.setElevenLabsApiKey(event.currentTarget.value)} />
                                    <p>Give ChatGPT a realisic human voice by connecting your ElevenLabs account (preview the available voices below). <a href="https://beta.elevenlabs.io" target="_blank">Click here to sign up.</a></p>
                                    <p>You can find your API key on the Profile tab of the ElevenLabs website. Your API key is stored only on this device and never transmitted to anyone except ElevenLabs.</p>
                                </section>
                            </Grid.Col>
                            <Grid.Col span={12}>
                                <section className={context.settings.option === 'elevenlabs-voice' ? 'focused' : ''}>
                                    <h3>Voice</h3>
                                    <Select
                                        value={context.voice.id}
                                        onChange={v => context.voice.setVoiceID(v!)}
                                        data={voices.map(v => ({ label: v.name, value: v.voice_id }))} />
                                    <audio controls style={{ display: 'none' }} id="voice-preview" key={context.voice.id}>
                                        <source src={voices.find(v => v.voice_id === context.voice.id)?.preview_url} type="audio/mpeg" />
                                    </audio>
                                    <Button onClick={() => document.getElementById('voice-preview')?.play()} variant='light' compact style={{ marginTop: '1rem' }}>
                                        <i className='fa fa-headphones' />
                                        <span>Preview voice</span>
                                    </Button>
                                </section>
                            </Grid.Col>
                        </Grid>
                    </Settings>
                </Tabs.Panel>
            </Tabs>
            <div id="save">
                <Button variant="light" fullWidth size="md" onClick={() => context.settings.close()}>
                    Save and Close
                </Button>
            </div>
        </Container>
    )
}