/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import React, { useReducer, useEffect, useState } from "react";
import { NavLink, matchRoutes, useLocation } from "react-router-dom";
import Button from "react-bootstrap/Button";
import rangerIcon from "Images/sidebar/ranger.svg";
import keyIcon from "Images/sidebar/key.svg";
import tagsIcon from "Images/sidebar/tags.svg";
import reportsIcon from "Images/sidebar/reports.svg";
import auditsIcon from "Images/sidebar/audits.svg";
import zoneIcon from "Images/sidebar/zone.svg";
import settingsIcon from "Images/sidebar/settings.svg";
import accountIcon from "Images/sidebar/account.svg";
import gdsIcon from "Images/sidebar/governed-data.svg";
import { fetchApi } from "Utils/fetchAPI";
import { getServiceDef, getUserProfile } from "Utils/appState";
import {
  hasAccessToTab,
  isAuditor,
  isKeyAdmin,
  isSystemAdmin,
  isKMSAuditor,
  getLandingPageURl
} from "Utils/XAUtils";
import { cloneDeep, filter, sortBy } from "lodash";
import { PathAssociateWithModule } from "Utils/XAEnums";
import { SideBarBody } from "./SideBarBody";

function reducer(state, action) {
  switch (action.type) {
    case "SET_LOADER":
      return {
        ...state,
        loader: action.loader
      };
    case "SERVICEDEF_DATA":
      return {
        ...state,
        allserviceDefData: action.allserviceDefData,
        serviceDefData: action.serviceDefData,
        tagServiceDefData: action.tagServiceDefData
      };
    case "SERVICES_DATA":
      return {
        ...state,
        allServiceData: action.allServiceData,
        serviceData: action.serviceData,
        tagServiceData: action.tagServiceData
      };
    case "SELECTED_SERVCIEDEF_DATA":
      return {
        ...state,
        selectedServiceDef: action.selectedServiceDef
      };

    default:
      throw new Error();
  }
}

export const SideBar = () => {
  const { allServiceDefs, serviceDefs, tagServiceDefs } = cloneDeep(
    getServiceDef()
  );
  const isKMSRole = isKeyAdmin() || isKMSAuditor();
  const [keyState, dispatch] = useReducer(reducer, {
    loader: false,
    allserviceDefData: allServiceDefs,
    serviceDefData: serviceDefs,
    tagServiceDefData: tagServiceDefs,
    allServiceData: [],
    serviceData: [],
    tagServiceData: [],
    selectedServiceDef: [],
    serviceTypesOptions: sortBy(
      filter(allServiceDefs, (serviceDef) => serviceDef.name !== "tag"),
      "name"
    )
  });

  const {
    loader,
    serviceData,
    tagServiceData,
    allServiceData,
    serviceDefData,
    tagServiceDefData,
    allserviceDefData
  } = keyState;

  const userProps = getUserProfile();
  const loginId = (
    <span className="login-id user-name p-0">{userProps?.loginId}</span>
  );

  let location = useLocation();
  let isListenerAttached = false;

  const [isActive, setActive] = useState(null);
  const [isDrawerOpen, setDrawer] = useState(false);
  const [accountDrawer, setAccountDrawer] = useState(false);

  const handleClickOutside = (e) => {
    if (
      document.getElementById("sidebar")?.contains(e?.target) == false &&
      document.getElementById("drawer-content")?.contains(e?.target) == false &&
      document.getElementById("account-drawer-content")?.contains(e?.target) ==
        false
    ) {
      setActive(null);
      setDrawer(false);
      setAccountDrawer(false);
    }
    e?.stopPropagation();
  };

  useEffect(() => {
    if (!isListenerAttached) {
      document?.addEventListener("mousedown", handleClickOutside);
      isListenerAttached = true;
      return;
    }
    return () => {
      document?.removeEventListener("mousedown", handleClickOutside);
    };
  }, []);

  const fetchServicesData = async () => {
    dispatch({
      type: "SET_LOADER",
      loader: true
    });

    let servicesResp = [];
    let resourceServices = [];
    let tagServices = [];

    try {
      servicesResp = await fetchApi({
        url: "public/v2/api/service-headers"
      });
      tagServices = filter(servicesResp?.data, ["type", "tag"]);
      if (isKMSRole) {
        resourceServices = filter(servicesResp?.data, ["type", "kms"]);
      } else {
        resourceServices = filter(
          servicesResp?.data,
          (service) => service.type !== "tag" && service.type !== "kms"
        );
      }

      dispatch({
        type: "SERVICES_DATA",
        allServiceData: servicesResp?.data || [],
        serviceData: resourceServices,
        tagServiceData: tagServices
      });
      dispatch({
        type: "SET_LOADER",
        loader: false
      });
    } catch (error) {
      console.error(
        `Error occurred while fetching Services or CSRF headers! ${error}`
      );
    }
  };

  const closeCollapse = () => {
    setActive(null);
    setDrawer(false);
    setAccountDrawer(false);
  };

  const activeClass = (modules) => {
    let allRouter = [];
    let PermissionPath = PathAssociateWithModule["Permission"]?.map((val) => ({
      path: val
    }));
    for (const key in PathAssociateWithModule) {
      if (key == modules) {
        allRouter = [...allRouter, ...PathAssociateWithModule[key]];
      }
    }
    let isValidRouter = matchRoutes(
      allRouter.map((val) => ({ path: val })),
      location.pathname
    );

    if (isValidRouter !== null && isValidRouter.length > 0) {
      return "navbar-active";
    } else if (
      matchRoutes(PermissionPath, location.pathname) &&
      modules == "Users/Groups"
    ) {
      return "navbar-active";
    } else {
      return;
    }
  };

  return (
    <React.Fragment>
      <nav id="sidebar">
        <div className="sidebar-header">
          <NavLink
            id="rangerIcon"
            to={getLandingPageURl()}
            onClick={() => {
              setActive(null);
              setDrawer(false);
              setAccountDrawer(false);
            }}
          >
            <img className="logo" src={rangerIcon} alt="Ranger logo" />
          </NavLink>
        </div>

        <ul className="list-unstyled components">
          {hasAccessToTab("Resource Based Policies") && (
            <li
              className={
                isActive !== null && isActive === "resourcesCollapse"
                  ? "selected"
                  : undefined
              }
            >
              <Button
                id="resourcesButton"
                className={activeClass("Resource Based Policies")}
                onClick={() => {
                  setActive("resourcesCollapse");
                  setAccountDrawer(false);
                  setDrawer(true);
                  fetchServicesData();
                }}
              >
                <img src={keyIcon} />
                <span>Resource Policies</span>
              </Button>
            </li>
          )}

          {hasAccessToTab("Tag Based Policies") && (
            <li
              className={
                isActive !== null && isActive === "tagCollapse"
                  ? "selected"
                  : undefined
              }
            >
              <Button
                id="tagButton"
                className={activeClass("Tag Based Policies")}
                onClick={() => {
                  setActive("tagCollapse");
                  setAccountDrawer(false);
                  setDrawer(true);
                  fetchServicesData();
                }}
              >
                <img src={tagsIcon} />
                <span>Tag Policies</span>
              </Button>
            </li>
          )}

          {hasAccessToTab("Governed Data Sharing") && (
            <li
              className={
                isActive !== null && isActive === "gdsCollapse"
                  ? "selected"
                  : undefined
              }
            >
              <Button
                id="gdsButton"
                className={activeClass("GDS")}
                onClick={() => {
                  setActive("gdsCollapse");
                  setAccountDrawer(false);
                  setDrawer(true);
                }}
              >
                <img src={gdsIcon} />
                <span>Governed Data Sharing</span>
              </Button>
            </li>
          )}

          {hasAccessToTab("Reports") && (
            <li>
              <NavLink
                to="/reports/userAccess?policyType=0"
                className={activeClass("Reports")}
                onClick={() => {
                  setActive(null);
                  setDrawer(false);
                  setAccountDrawer(false);
                }}
              >
                <img src={reportsIcon} />
                <span>Reports</span>
              </NavLink>
            </li>
          )}

          {hasAccessToTab("Audit") && (
            <li
              className={
                isActive !== null && isActive === "auditCollapse"
                  ? "selected"
                  : undefined
              }
            >
              <Button
                className={activeClass("Audit")}
                onClick={() => {
                  setActive("auditCollapse");
                  setAccountDrawer(false);
                  setDrawer(true);
                }}
              >
                <img src={auditsIcon} />
                <span>Audits</span>
              </Button>
            </li>
          )}

          {hasAccessToTab("Security Zone") && (
            <React.Fragment>
              {!isKMSRole && (
                <li>
                  <NavLink
                    className={activeClass("Security Zone")}
                    to="/zones/zone/list"
                    onClick={() => {
                      setActive(null);
                      setDrawer(false);
                      setAccountDrawer(false);
                    }}
                  >
                    <img src={zoneIcon} />
                    <span>Security Zone</span>
                  </NavLink>
                </li>
              )}
            </React.Fragment>
          )}

          {hasAccessToTab("Key Manager") && (
            <React.Fragment>
              <li>
                <NavLink
                  className={activeClass("Key Manager")}
                  to="/kms/keys/new/manage/service"
                  onClick={() => {
                    setActive(null);
                    setDrawer(false);
                    setAccountDrawer(false);
                  }}
                >
                  <i className="fa fa-fw fa-key"></i>
                  <span>Key Manager</span>
                </NavLink>
              </li>
            </React.Fragment>
          )}

          {(hasAccessToTab("Users/Groups") ||
            isAuditor() ||
            isSystemAdmin()) && (
            <li
              className={
                isActive !== null && isActive === "settingsCollapse"
                  ? "selected"
                  : undefined
              }
            >
              <Button
                className={activeClass("Users/Groups")}
                onClick={() => {
                  setActive("settingsCollapse");
                  setAccountDrawer(false);
                  setDrawer(true);
                }}
              >
                <img src={settingsIcon} />
                <span>Settings</span>
              </Button>
            </li>
          )}

          <li
            className={
              isActive !== null && isActive === "accountCollapse"
                ? "selected"
                : undefined
            }
          >
            <Button
              className={activeClass("Profile")}
              onClick={() => {
                setActive("accountCollapse");
                setDrawer(false);
                setAccountDrawer(true);
              }}
            >
              <img src={accountIcon} />
              <span title={userProps?.loginId}>{loginId}</span>
            </Button>
          </li>
        </ul>
      </nav>

      <SideBarBody
        allServicesDefData={allserviceDefData}
        servicesDefData={serviceDefData}
        tagServicesDefData={tagServiceDefData}
        allServicesData={allServiceData}
        servicesData={serviceData}
        tagServicesData={tagServiceData}
        loader={loader}
        activeMenu={isActive}
        isDrawerOpen={isDrawerOpen}
        accountDrawer={accountDrawer}
        closeCollapse={closeCollapse}
        sideBarDispatch={dispatch}
      />
    </React.Fragment>
  );
};

export default SideBar;
