/** @jsx jsx */
import { jsx } from '@emotion/core';
import styled from '@emotion/styled';
import { useCallback, useContext, useMemo } from 'react';
import { gray100, gray200, blue500, gray600, gray700, gray800, gray300 } from '../../styles/colors_v2';
import { ClearButton, CornerButton } from '../../styles/elements';
import { CommandCategory, StoredCommand } from '../../types';
import { ReactComponent as EditIcon } from '../../icons/Edit.svg';
import { ReactComponent as EffectIcon } from '../../icons/Effect.svg';
import { ReactComponent as GeneratorIcon } from '../../icons/Generator.svg';
import { CommandEditorContext } from '../../hooks/useCommandEditor';
import { ScreenConfigurationContext } from '../../hooks/useScreenConfiguration';
import WalkthroughFlag from '../WalkthroughFlag';
import { WalkthroughStep } from '../../hooks/useWalkthrough';
import { ProjectContext } from '../../hooks/useProject';
import { CommandLibraryContext } from '../../hooks/useCommandLibrary';


const Wrapper = styled.div`
  min-height: 0;
  background-color: ${gray100};
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 3;
  grid-row-end: 4;
  overflow: scroll;
  ::-webkit-scrollbar {
    display: none;
  }
  padding: 20px 40px;
`;

const Content = styled.div`
  margin: 0 auto;
  color: ${gray800};
  max-width: 1400px;
  width: 100%;
  display: grid;
  grid-template-rows: 40px auto auto auto;
  grid-template-columns: 1fr 1fr;
  column-gap: 4px;
  row-gap: 4px;
`;

const FilterTabs = styled.div`
  grid-column-start: 1;
  grid-column-end: 3;
  padding: 10px 40px;
  display: flex;
  justify-content: flex-start;
  align-items: center;
`;

const FilterTab = styled(ClearButton)<{ active: boolean }>`
  background-color: transparent;
  text-align: left;
  min-width: 128px;
  padding: 4px 20px 6px 4px;
  margin: 0 20px 0 -4px;
  display: block;
  font-weight: ${({ active }) => active ? 600 : 400};
  color: ${({ active }) => active ? gray800 : gray600};
  &:hover {
    color: ${({ active }) => active ? gray800 : blue500};
  }
  position: relative;
  &:after {
    content: '';
    display: block;
    position: absolute;
    bottom: 2px;
    left: 4px;
    right: 4px;
    height: ${({ active }) => active ? '3px' : '1px'};
    background-color: currentColor;
  }
`;

const Section = styled.div``;

const SectionContent = styled.div`
  width: 100%;
  max-width: 500px;
  padding: 30px 40px;
  border-radius: 2px;
`;

const SectionTitle = styled.h3`
  font-size: 24px;
  margin: 0;
  padding: 0;
  font-family: 'Lexend Peta', 'Helvetica Neue', Helvetica, Arial, sans-serif;
`;

const SectionSubtitle = styled.h3`
  color: ${gray700};
  font-size: 13px;
  font-weight: 600;
  margin-top: 20px;
  margin-bottom: 20px;
`;


const SectionBody = styled.p`
  font-size: 16px;
  line-height: 24px;
  margin: 16px 0 0 0;
  padding: 0;
  &:first-of-type {
    margin-top: 32px;
  }
`;

const Explanation = styled(SectionContent)`
  background-color: ${gray200};
`;

const CommandList = styled.div`
  margin-left: -8px;
`;

const CommandEntryWrapper = styled(CornerButton)`
  background-color: ${gray200};
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  text-align: left;
  margin-bottom: 8px;
  padding: 8px 8px 8px 8px;
  &:hover {
    background-color: ${gray300};
    &:after {
      border-top-color: ${gray300};
    }
  }
  &:after {
    border-top: 24px solid ${gray200};
  }
`;
const CommandArtwork = styled.div`
  flex-shrink: 0;
  border: 1px solid ${gray800};
  width: 64px;
  height: 64px;
  margin-right: 24px;
  border-radius: 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  svg * {
    fill: ${gray800};
  }
`;
const CommandTitle = styled.h3`
  font-size: 16px;
  font-weight: 600;
  margin: 0;
  padding: 0;
`;
const CommandAuthor = styled.h4`
  font-size: 13px;
  font-weight: 400;
  color: ${gray600};
  margin: 0;
  padding: 0;
`;
const CommandDescription = styled.p`
  font-size: 13px;
  margin: 8px 0 0 0;
  padding: 0;
`;
const CommandBody = styled.div``;

const CommandIcon = ({ category }: { category: CommandCategory }) => {
  if (category === CommandCategory.Edit) {
    return <EditIcon />;
  } else if (category === CommandCategory.Effect) {
    return <EffectIcon />;
  } else if (category === CommandCategory.Generator) {
    return <GeneratorIcon />;
  } else {
    return null;
  }
};

const CommandEntry = ({ command, onOpen, flag }: { command: StoredCommand, onOpen: (command: StoredCommand) => void; flag: boolean }) => {
  const commandEditor = useContext(CommandEditorContext);
  return (
    <CommandEntryWrapper onClick={() => {
      commandEditor.openSavedCommand(command)
      onOpen(command);
    }}>
      {flag && (
        <WalkthroughFlag
          style={{ left: 'calc(100% + 24px)', top: 0, width: 200 }}
          anchorStyle={{ bottom: '50%', marginBottom: -11, left: 3 }}
          step={WalkthroughStep.OpenCode}
        >
          Click on this thing to open some code!
        </WalkthroughFlag>
      )}
      <CommandArtwork>
        <CommandIcon category={command.category} />
      </CommandArtwork>
      <CommandBody>
        <CommandTitle>{command.name}</CommandTitle>
        {command.author_name && <CommandAuthor>by {command.author_name}</CommandAuthor>}
        <CommandDescription>{command.description}</CommandDescription>
      </CommandBody>
    </CommandEntryWrapper>
  );
}

const EmptyMessage = styled.p`
  color: ${gray600};
  background-color: ${gray200};
  padding: 8px;
  border-radius: 2px;
  text-align: center;
  a {
    color: inherit;
    text-decoration: underline;
    &:hover {
      cursor: pointer;
    }
  }
`;

const LibrarySection = (
  { title, subtitle, commands, onOpenCommand, onClearFilters, flagCommandId }:
  { title: string, subtitle: string, commands: StoredCommand[], onOpenCommand: (command: StoredCommand) => void, onClearFilters: () => void, flagCommandId?: number | string }
) => (
  <Section>
    <SectionContent>
      <SectionTitle>{title}</SectionTitle>
      <SectionSubtitle>{subtitle}</SectionSubtitle>
      <CommandList>
        {
          commands.length === 0
            ? (
              <EmptyMessage>
                Looks like there's nothing here.<br />
                Try <a onClick={onClearFilters}>clearing filters</a>.
              </EmptyMessage>
            ) : commands.map((command, index) => (
              <CommandEntry onOpen={onOpenCommand} command={command} key={index} flag={flagCommandId === command.id}/>
            ))
        }
      </CommandList>
    </SectionContent>
  </Section>
);

export default () => {
  const { libraryFilterState, setLibraryFilterState } = useContext(ScreenConfigurationContext);
  const { commands, onOpenCommand } = useContext(CommandLibraryContext);
  const { state } = useContext(ProjectContext);
  const filteredCommands = useMemo(() => {
    if (!libraryFilterState) {
      return commands;
    }
    return Object.keys(commands).reduce((a, c) => ({
      ...a,
      [c]: commands[c as any as keyof typeof commands].filter(({ category }) => category === libraryFilterState)
    }), {});
  }, [commands, libraryFilterState]) as typeof commands;

  const clearFilters = useCallback(
    () => {
      setLibraryFilterState(null);
    },
    [setLibraryFilterState]
  );

  return (
    <Wrapper>
      <Content>
        <FilterTabs>
          <FilterTab
            onClick={() => setLibraryFilterState(null)}
            active={libraryFilterState === null}
          >
            Everything
          </FilterTab>
          <FilterTab
            onClick={() => setLibraryFilterState(CommandCategory.Generator)}
            active={libraryFilterState === CommandCategory.Generator}
          >
            Generators
          </FilterTab>
          <FilterTab
            onClick={() => setLibraryFilterState(CommandCategory.Effect)}
            active={libraryFilterState === CommandCategory.Effect}
          >
            Effects
          </FilterTab>
          <FilterTab
            onClick={() => setLibraryFilterState(CommandCategory.Edit)}
            active={libraryFilterState === CommandCategory.Edit}
          >
            Edits
          </FilterTab>
        </FilterTabs>
        {commands.recent.length >= 3 && (
          <LibrarySection
            onOpenCommand={onOpenCommand}
            onClearFilters={clearFilters}
            title="Recent"
            subtitle="The last few commands you had open."
            commands={filteredCommands.recent}
          />
        )}
        <LibrarySection
          flagCommandId={state.tracks.length === 0 ? 'click' : 'timeTravelDelay' }
          onOpenCommand={onOpenCommand}
          onClearFilters={clearFilters}
          title="Start Here"
          subtitle="Simple, instructive examples, with helpful comments."
          commands={filteredCommands.starter}
        />
        {commands.recent.length < 3 && (
          <Section>
            <Explanation>
              <SectionTitle>Hold up. What is this?</SectionTitle>
              <SectionBody>You're looking at WavTool's code library!</SectionBody>
              <SectionBody>Here you can find JS audio programs written by us, and by other WavTool users.</SectionBody>
              <SectionBody>You can <strong>run, edit, and save your own versions</strong> of anything you find here.</SectionBody>
            </Explanation>
          </Section>
        )}
        <LibrarySection
          onOpenCommand={onOpenCommand}
          onClearFilters={clearFilters}
          title="Essential Edits"
          subtitle="These are so useful that we've given them keyboard shortcuts!"
          commands={filteredCommands.essentials}
        />
        <LibrarySection
          onOpenCommand={onOpenCommand}
          onClearFilters={clearFilters}
          title="WavTool Classics"
          subtitle="The first lines of code ever tested with WavTool!"
          commands={filteredCommands.favourites}
        />
        <LibrarySection
          onOpenCommand={onOpenCommand}
          onClearFilters={clearFilters}
          title="Community"
          subtitle="Code from other WavTool users."
          commands={filteredCommands.community}
        />
      </Content>
    </Wrapper>
  )
};
