// Copyright 2020 Northern.tech AS
//
//    Licensed 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 DeviceIdentityDisplay from '@northern.tech/common-ui/DeviceIdentity';
import { Link } from '@northern.tech/common-ui/Link';
import TextOverflowMultiline from '@northern.tech/common-ui/TextOverflowMultiline';
import Time from '@northern.tech/common-ui/Time';
import { DEPLOYMENT_ROUTES, auditlogTypes, canAccess } from '@northern.tech/store/constants';
import { generateReleasesPath } from '@northern.tech/store/locationutils';

const ArtifactLink = ({ item }) => <Link to={generateReleasesPath({ pageState: { selectedRelease: item.object.artifact.name } })}>View software</Link>;
const DeploymentLink = ({ item }) => <Link to={`${DEPLOYMENT_ROUTES.finished.route}?open=true&id=${item.object.id}`}>View deployment</Link>;
const DeviceLink = ({ item }) => <Link to={`/devices?id=${item.object.id}`}>View device</Link>;
const DeviceRejectedLink = ({ item }) => <Link to={`/devices/rejected?id=${item.object.id}`}>View device</Link>;
const TerminalSessionLink = () => <Link>View session log</Link>;
const ChangeFallback = props => {
  const {
    item: { change = '-' }
  } = props;
  return <TextOverflowMultiline>{change}</TextOverflowMultiline>;
};

const FallbackFormatter = props => {
  let result = '';
  try {
    result = JSON.stringify(props);
  } catch (error) {
    console.log(error);
  }
  return <div>{result}</div>;
};

const ArtifactFormatter = ({ artifact }) => <TextOverflowMultiline>{artifact.name}</TextOverflowMultiline>;
const DeploymentFormatter = ({ deployment }) => <TextOverflowMultiline>{deployment.name}</TextOverflowMultiline>;
const DeviceFormatter = ({ id }) => <DeviceIdentityDisplay device={{ id }} />;
const UserFormatter = ({ user }) => <TextOverflowMultiline>{user.email}</TextOverflowMultiline>;
const TenantFormatter = ({ tenant }) => <TextOverflowMultiline>{tenant.name}</TextOverflowMultiline>;

const defaultAccess = canAccess;
const changeMap = {
  default: { component: 'div', actionFormatter: FallbackFormatter, title: 'defaultTitle', accessCheck: defaultAccess },
  artifact: { actionFormatter: ArtifactFormatter, component: ArtifactLink, accessCheck: ({ canReadReleases }) => canReadReleases },
  deployment: {
    actionFormatter: DeploymentFormatter,
    component: DeploymentLink,
    accessCheck: ({ canReadDeployments }) => canReadDeployments
  },
  deviceDecommissioned: { actionFormatter: DeviceFormatter, component: 'div', accessCheck: defaultAccess },
  deviceRejected: { actionFormatter: DeviceFormatter, component: DeviceRejectedLink, accessCheck: ({ canReadDevices }) => canReadDevices },
  deviceGeneral: { actionFormatter: DeviceFormatter, component: DeviceLink, accessCheck: ({ canReadDevices }) => canReadDevices },
  deviceTerminalSession: { actionFormatter: DeviceFormatter, component: TerminalSessionLink, accessCheck: defaultAccess },
  user: { actionFormatter: UserFormatter, component: ChangeFallback, accessCheck: defaultAccess },
  user_access_token: { actionFormatter: FallbackFormatter, component: ChangeFallback, accessCheck: defaultAccess },
  tenant: { actionFormatter: TenantFormatter, component: ChangeFallback, accessCheck: defaultAccess }
};

const mapChangeToContent = item => {
  let content = changeMap[item.object.type];
  if (content) {
    return content;
  } else if (item.object.type === 'device' && item.action.includes('terminal')) {
    content = changeMap.deviceTerminalSession;
  } else if (item.object.type === 'device' && item.action.includes('reject')) {
    content = changeMap.deviceRejected;
  } else if (item.object.type === 'device' && item.action.includes('decommission')) {
    content = changeMap.deviceDecommissioned;
  } else if (item.object.type === 'device') {
    content = changeMap.deviceGeneral;
  } else {
    content = changeMap.default;
  }
  return content;
};

const actorMap = {
  user: 'email',
  device: 'id'
};

export const UserDescriptor = (item, index) => (
  <TextOverflowMultiline key={`${item.time}-${index}`}>{item.actor[actorMap[item.actor.type]]}</TextOverflowMultiline>
);
export const ActionDescriptor = (item, index) => (
  <TextOverflowMultiline className="uppercased" key={`${item.time}-${index}`}>
    {item.action}
  </TextOverflowMultiline>
);
export const TypeDescriptor = (item, index) => (
  <TextOverflowMultiline className="capitalized" key={`${item.time}-${index}`}>
    {auditlogTypes[item.object.type]?.title ?? item.object.type}
  </TextOverflowMultiline>
);
export const ChangeDescriptor = (item, index) => {
  const FormatterComponent = mapChangeToContent(item).actionFormatter;
  return <FormatterComponent key={`${item.time}-${index}`} {...item.object} />;
};
export const ChangeDetailsDescriptor = (item, index, userCapabilities) => {
  const { component: Comp, accessCheck } = mapChangeToContent(item);
  const key = `${item.time}-${index}`;
  return accessCheck(userCapabilities) ? <Comp key={key} item={item} /> : <div key={key} />;
};
export const TimeWrapper = (item, index) => <Time key={`${item.time}-${index}`} value={item.time} />;
