import { useEffect, useCallback } from 'react';
import {
  useRecoilValue,
  useSetRecoilState,
  atomFamily,
  selectorFamily,
} from 'recoil';

import { authState } from '../lib/personium_auth_adapter';
import { statListener, adapter, getYMD } from '../adapters/locations_direct';
import { setACL, statDirectory } from '../adapters/webdav';

export const locationODataFromId = selectorFamily({
  key: '_locationODataFromId',
  get: locationId => async ({ get }) => {
    console.log('locationODataFromId');
    const result = await adapter
      .getMoveDetail(locationId)
      .catch(res => adapter.getStayDetail(locationId))
      .catch(res => console.log('fetch error', res));
    return result;
  },
});

export const locationURLFromId = selectorFamily({
  key: '_locationURLFromId',
  get: locationId => ({ get }) => {
    // const odata = useRecoilValue(locationODataFromId(locationId));
    const odata = get(locationODataFromId(locationId));
    const timems = parseInt(odata.startTime.match(/\/Date\((\d+)\)\//)[1]);
    const filename = `${'placeId' in odata ? 's' : 'm'}_${timems}.json`;
    const folder = `${authState.boxUrl}locations/${getYMD(timems)}/`;
    const filepath = `${folder}${filename}`;
    return filepath;
  },
});

// todo: refactoring
export const locationACLStatusState = atomFamily({
  key: 'Location ACL Status',
  default: 'loading',
});

export function useLocationACLSubscribe(__id, filepath) {
  const setAclStatus = useSetRecoilState(locationACLStatusState(__id));

  useEffect(() => {
    function handleStatChange(stat) {
      if ('acl' in stat && stat.acl.has('DAV::all')) {
        setAclStatus(
          stat.acl.get('DAV::all').has('DAV::read') ? 'public' : 'private'
        );
      } else {
        setAclStatus('private');
      }
    }

    statListener.subscribe(filepath, handleStatChange);
    return function cleanup() {
      statListener.unsubscribe(filepath, handleStatChange);
    };
  }, []);

  const setLocationACLPrivate = useCallback(() => {
    setAclStatus('loading');
    setACL(filepath, authState.accessToken.access_token, []).then(() => {
      statListener.fire(filepath, { acl: new Map([]) }); // Todo: use PROPFIND to get current stat.
    });
  }, [__id, filepath]);

  const setLocationACLPublic = useCallback(() => {
    setAclStatus('loading');
    setACL(filepath, authState.accessToken.access_token, [
      { principal: 'DAV::all', privileges: ['DAV::read'] },
    ]).then(() => {
      statListener.fire(filepath, {
        acl: new Map([['DAV::all', new Set(['DAV::read'])]]), // Todo: use PROPFIND to get current stat.
      });
    });
  }, [__id, filepath]);

  const updateLocationACL = useCallback(() => {
    statDirectory(filepath, authState.accessToken.access_token).then(res => {
      if (!res.has(filepath)) {
        console.log(`${filepath} is not found(PROPPATCH)`);
        return;
      }
      statListener.fire(filepath, res.get(filepath));
    });
  });

  return { updateLocationACL, setLocationACLPrivate, setLocationACLPublic };
}