import React from "react";
import classNames from "classnames";
import PropTypes from "prop-types";

import Link from "../Link";
import Badge from "../Badge";
import IconLink from "./IconLink";
import CurrentUserMenu from "./CurrentUserMenu";

const LINK = "link";
const PUSH_STATE = "pushstate";
const BUTTON = "button";

const linkPropTypes = {
    /** CSS class names. */
    className: PropTypes.string,
    /* Boolean, whether an external icon should show */
    hasExternalIcon: PropTypes.bool,
    /** Should show a separator line before this link. */
    hasSeparator: PropTypes.bool,
    /** Url to Navigate to when type is link. */
    href: PropTypes.string,
    /** Name of Icon. */
    iconName: PropTypes.string.isRequired,
    /** Whether the link is highlighted blue as the current active nav link. */
    isActive: PropTypes.bool,
    /** Condition in which this link is visible. */
    isVisible: PropTypes.bool,
    /** Description of url. */
    linkLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
    /** Handler called when link is clicked. */
    onClick: PropTypes.func,
    /** Name of test data section. */
    testSection: PropTypes.string,
    /** Type of Link. */
    type: PropTypes.oneOf([LINK, PUSH_STATE, BUTTON]),
};

const linkDefaultProps = {
    href: "",
    isActive: false,
    isVisible: true,
    linkLabel: "",
    testSection: null,
    hasSeparator: false,
    onClick: () => null,
    type: LINK,
};

const PrimaryLink = props => <IconLink {...props} isSecondaryLink={false} />;
PrimaryLink.propTypes = linkPropTypes;
PrimaryLink.defaultProps = linkDefaultProps;
PrimaryLink.displayName = "NavBar.PrimaryLink";

const SecondaryLink = props => <IconLink {...props} isSecondaryLink={true} />;
SecondaryLink.propTypes = linkPropTypes;
SecondaryLink.defaultProps = linkDefaultProps;
SecondaryLink.displayName = "NavBar.SecondaryLink";

/**
 *
 * @param {Object} props - Properties passed to component
 * @returns {ReactElement}
 */

const NavBar = ({
    badgeText,
    children,
    className,
    footerContent,
    homeUrl,
    isOpen,
    logoUrl,
    title,
    trialContent,
    ...props
}) => {
    const renderChildrenByType = ComponentType =>
        React.Children.toArray(children)
            .filter(child => child.type === ComponentType)
            .map(element => React.cloneElement(element, { isOpen }));

    const logoClasses = classNames("push-double--left", {
        "root-nav__logo--full": isOpen,
        "root-nav__logo--mark": !isOpen,
    });

    const renderPrivacy = () => {
        let year = new Date().getFullYear();
        return (
            <div className="root-nav__user root-nav__link root-nav__link--plain hard--bottom muted">
                <span className="display--inline-block">
                    ©2010&ndash;{year} Optimizely.{" "}
                    <a href="https://www.optimizely.com/privacy/" className="muted underline">
                        Privacy
                    </a>
                </span>
            </div>
        );
    };

    const renderFooterContent = () => {
        return (
            <React.Fragment>
                <hr className="oui-rule push-double--sides hard" />
                <div className="root-nav__link root-nav__link--plain flex flex--column flex--1">{footerContent}</div>
            </React.Fragment>
        );
    };

    return (
        <nav
            className={classNames({
                "root-nav": true,
                "root-nav--open": isOpen,
            }, className)}
            data-test-section="p13n-root-navbar"
            {...props}
        >
            <div data-test-section="navbar-header">
                {logoUrl  && (
                    <div className="root-nav__logo push--bottom">
                        <Link href={homeUrl}>
                            <img alt="logo" src={logoUrl} className={logoClasses} />
                        </Link>
                    </div>
                )}
                {trialContent}
                <div
                    className={classNames({
                        "root-nav__project": true,
                        "root-nav-fader": !isOpen,
                    })}
                >
                    <div className="epsilon truncate" data-test-section="project-name">
                        {title}
                    </div>
                    <Badge color="purple" testSection="project-badge">
                        {badgeText}
                    </Badge>
                </div>
            </div>
            <ul className="push--ends">{renderChildrenByType(PrimaryLink)}</ul>
            <div className="anchor--bottom">
                <ul className="push--ends">{renderChildrenByType(SecondaryLink)}</ul>
                {renderChildrenByType(CurrentUserMenu)}
                {isOpen && footerContent && renderFooterContent()}
                {isOpen && renderPrivacy()}
            </div>
        </nav>
    );
};

NavBar.propTypes = {
    /** Text to appear below title in a badge. */
    badgeText: PropTypes.string,
    /** Allowed Children are <NavBar.PrimaryLink>, <NavBar.SecondaryLink>, <NavBar.CurrentUserMenu>. Only one of <NavBar.CurrentUserMenu> is allowed. */
    children: (props, propName) => {
        const prop = props[propName];
        let error = null;
        React.Children.forEach(prop, child => {
            if (child === null) {
                // Skip checking empty child nodes
                return;
            }
            if (![SecondaryLink, PrimaryLink, CurrentUserMenu].includes(child.type)) {
                error = new Error("Children should be of type PrimaryLink, SecondaryLink, or CurrentUserMenu.");
            }
        });
        if (!error && React.Children.toArray(prop).filter(child => child.type === CurrentUserMenu).length !== 1) {
            error = new Error("There should be only one instance of `CurrentUserMenu`");
        }
        return error;
    },
    /** CSS class names. */
    className: PropTypes.string,
    /** Component to appear above the privacy statement. */
    footerContent: PropTypes.node,
    /** Url to navigate to when Brand Logo is clicked. */
    homeUrl: PropTypes.string,
    /** Is Navigation Bar open or closed. */
    isOpen: PropTypes.bool,
    /** Brand logo URL. */
    logoUrl: PropTypes.string,
    /** Title of navigation bar */
    title: PropTypes.string,
    /** Component to appear above title and below brand logo. */
    trialContent: PropTypes.node,
};

NavBar.defaultProps = {
    badgeText: "",
    homeUrl: "",
    isOpen: true,
    logoUrl: null,
    title: "",
    trialContent: null,
};

NavBar.PrimaryLink = PrimaryLink;
NavBar.SecondaryLink = SecondaryLink;
NavBar.CurrentUserMenu = CurrentUserMenu;

export default NavBar;
