const DEFAULT_COLORMAP = '2hot';
const toolGroupIds = {
  pt: 'dynamic4D-pt',
  fusion: 'dynamic4D-fusion',
  ct: 'dynamic4D-ct',
};

function getPTOptions({
  colormap,
  voiInverted,
}: {
  colormap?: {
    name: string;
    opacity:
      | number
      | {
          value: number;
          opacity: number;
        }[];
  };
  voiInverted?: boolean;
} = {}) {
  return {
    blendMode: 'MIP',
    colormap,
    voi: {
      windowWidth: 5,
      windowCenter: 2.5,
    },
    voiInverted,
  };
}

function getPTViewports() {
  const ptOptionsParams = {
    colormap: {
      name: DEFAULT_COLORMAP,
      opacity: [
        { value: 0, opacity: 0 },
        { value: 0.1, opacity: 1 },
        { value: 1, opacity: 1 },
      ],
    },
    voiInverted: false,
  };

  return [
    {
      viewportOptions: {
        viewportId: 'ptAxial',
        viewportType: 'volume',
        orientation: 'axial',
        toolGroupId: toolGroupIds.pt,
        initialImageOptions: {
          preset: 'middle', // 'first', 'last', 'middle'
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'axialSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ptWLSync',
            source: true,
            target: true,
          },
        ],
      },
      displaySets: [
        {
          id: 'ptDisplaySet',
          options: { ...getPTOptions(ptOptionsParams) },
        },
      ],
    },
    {
      viewportOptions: {
        viewportId: 'ptSagittal',
        viewportType: 'volume',
        orientation: 'sagittal',
        toolGroupId: toolGroupIds.pt,
        initialImageOptions: {
          preset: 'middle', // 'first', 'last', 'middle'
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'sagittalSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ptWLSync',
            source: true,
            target: true,
          },
        ],
      },
      displaySets: [
        {
          id: 'ptDisplaySet',
          options: { ...getPTOptions(ptOptionsParams) },
        },
      ],
    },
    {
      viewportOptions: {
        viewportId: 'ptCoronal',
        viewportType: 'volume',
        orientation: 'coronal',
        toolGroupId: toolGroupIds.pt,
        initialImageOptions: {
          preset: 'middle', // 'first', 'last', 'middle'
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'coronalSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ptWLSync',
            source: true,
            target: true,
          },
        ],
      },
      displaySets: [
        {
          id: 'ptDisplaySet',
          options: { ...getPTOptions(ptOptionsParams) },
        },
      ],
    },
  ];
}

function getFusionViewports() {
  const ptOptionsParams = {
    colormap: {
      name: DEFAULT_COLORMAP,
      opacity: [
        { value: 0, opacity: 0 },
        { value: 0.1, opacity: 0.8 },
        { value: 1, opacity: 0.8 },
      ],
    },
  };

  return [
    {
      viewportOptions: {
        viewportId: 'fusionAxial',
        viewportType: 'volume',
        orientation: 'axial',
        toolGroupId: toolGroupIds.fusion,
        initialImageOptions: {
          preset: 'middle', // 'first', 'last', 'middle'
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'axialSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ctWLSync',
            source: false,
            target: true,
          },
          {
            type: 'voi',
            id: 'fusionWLSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ptFusionWLSync',
            source: false,
            target: true,
            options: {
              syncInvertState: false,
            },
          },
          {
            type: 'hydrateseg',
            id: 'sameFORId',
            source: true,
            target: true,
            options: {
              matchingRules: ['sameFOR'],
            },
          },
        ],
      },
      displaySets: [
        {
          id: 'ctDisplaySet',
        },
        {
          options: { ...getPTOptions(ptOptionsParams) },
          id: 'ptDisplaySet',
        },
      ],
    },
    {
      viewportOptions: {
        viewportId: 'fusionSagittal',
        viewportType: 'volume',
        orientation: 'sagittal',
        toolGroupId: toolGroupIds.fusion,
        initialImageOptions: {
          preset: 'middle', // 'first', 'last', 'middle'
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'sagittalSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ctWLSync',
            source: false,
            target: true,
          },
          {
            type: 'voi',
            id: 'fusionWLSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ptFusionWLSync',
            source: false,
            target: true,
            options: {
              syncInvertState: false,
            },
          },
          {
            type: 'hydrateseg',
            id: 'sameFORId',
            source: true,
            target: true,
            options: {
              matchingRules: ['sameFOR'],
            },
          },
        ],
      },
      displaySets: [
        {
          id: 'ctDisplaySet',
        },
        {
          options: { ...getPTOptions(ptOptionsParams) },
          id: 'ptDisplaySet',
        },
      ],
    },
    {
      viewportOptions: {
        viewportId: 'fusionCoronal',
        viewportType: 'volume',
        orientation: 'coronal',
        toolGroupId: toolGroupIds.fusion,
        initialImageOptions: {
          preset: 'middle', // 'first', 'last', 'middle'
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'coronalSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ctWLSync',
            source: false,
            target: true,
          },
          {
            type: 'voi',
            id: 'fusionWLSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ptFusionWLSync',
            source: false,
            target: true,
            options: {
              syncInvertState: false,
            },
          },
          {
            type: 'hydrateseg',
            id: 'sameFORId',
            source: true,
            target: true,
            options: {
              matchingRules: ['sameFOR'],
            },
          },
        ],
      },
      displaySets: [
        {
          id: 'ctDisplaySet',
        },
        {
          options: { ...getPTOptions(ptOptionsParams) },
          id: 'ptDisplaySet',
        },
      ],
    },
  ];
}

function getSeriesChartViewport() {
  return {
    viewportOptions: {
      viewportId: 'seriesChart',
    },
    displaySets: [
      {
        id: 'chartDisplaySet',
        options: {
          // This dataset does not require the download of any instance since it is pre-computed locally,
          // but interleaveTopToBottom.ts was not loading any series because it consider that all viewports
          // are a Cornerstone viewport which is not true in this case and it waits for all viewports to
          // have called interleaveTopToBottom(...).
          skipLoading: true,
        },
      },
    ],
  };
}

function getCTViewports() {
  return [
    {
      viewportOptions: {
        viewportId: 'ctAxial',
        viewportType: 'volume',
        orientation: 'axial',
        toolGroupId: toolGroupIds.ct,
        initialImageOptions: {
          preset: 'middle', // 'first', 'last', 'middle'
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'axialSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ctWLSync',
            source: true,
            target: true,
          },
        ],
      },
      displaySets: [
        {
          id: 'ctDisplaySet',
        },
      ],
    },
    {
      viewportOptions: {
        viewportId: 'ctSagittal',
        viewportType: 'volume',
        orientation: 'sagittal',
        toolGroupId: toolGroupIds.ct,
        initialImageOptions: {
          preset: 'middle',
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'sagittalSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ctWLSync',
            source: true,
            target: true,
          },
        ],
      },
      displaySets: [
        {
          id: 'ctDisplaySet',
        },
      ],
    },
    {
      viewportOptions: {
        viewportId: 'ctCoronal',
        viewportType: 'volume',
        orientation: 'coronal',
        toolGroupId: toolGroupIds.ct,
        initialImageOptions: {
          preset: 'middle',
        },
        syncGroups: [
          {
            type: 'cameraPosition',
            id: 'coronalSync',
            source: true,
            target: true,
          },
          {
            type: 'voi',
            id: 'ctWLSync',
            source: true,
            target: true,
          },
        ],
      },
      displaySets: [
        {
          id: 'ctDisplaySet',
        },
      ],
    },
  ];
}

const defaultProtocol = {
  id: 'default4D',
  locked: true,
  // Don't store this hanging protocol as it applies to the currently active
  // display set by default
  // cacheId: null,
  hasUpdatedPriorsInformation: false,
  name: 'Default',
  createdDate: '2023-01-01T00:00:00.000Z',
  modifiedDate: '2023-01-01T00:00:00.000Z',
  availableTo: {},
  editableBy: {},
  imageLoadStrategy: 'default', // "default" , "interleaveTopToBottom",  "interleaveCenter"
  protocolMatchingRules: [
    {
      attribute: 'ModalitiesInStudy',
      constraint: {
        contains: ['CT', 'PT'],
      },
    },
  ],
  // -1 would be used to indicate active only, whereas other values are
  // the number of required priors referenced - so 0 means active with
  // 0 or more priors.
  numberOfPriorsReferenced: -1,
  displaySetSelectors: {
    defaultDisplaySetId: {
      // Unused currently
      imageMatchingRules: [],
      // Matches displaysets, NOT series
      seriesMatchingRules: [
        // Try to match series with images by default, to prevent weird display
        // on SEG/SR containing studies
        {
          attribute: 'numImageFrames',
          constraint: {
            greaterThan: { value: 0 },
          },
        },
      ],
      // Can be used to select matching studies
      // studyMatchingRules: [],
    },
    ctDisplaySet: {
      // Unused currently
      imageMatchingRules: [],
      // Matches displaysets, NOT series
      seriesMatchingRules: [
        {
          attribute: 'Modality',
          constraint: {
            equals: {
              value: 'CT',
            },
          },
          required: true,
        },
        {
          attribute: 'isReconstructable',
          constraint: {
            equals: {
              value: true,
            },
          },
          required: true,
        },
      ],
      // Can be used to select matching studies
      // studyMatchingRules: [],
    },
    ptDisplaySet: {
      // Unused currently
      imageMatchingRules: [],
      // Matches displaysets, NOT series
      seriesMatchingRules: [
        {
          attribute: 'Modality',
          constraint: {
            equals: 'PT',
          },
          required: true,
        },
        {
          attribute: 'isReconstructable',
          constraint: {
            equals: {
              value: true,
            },
          },
          required: true,
        },
        {
          attribute: 'SeriesDescription',
          constraint: {
            contains: 'Corrected',
          },
        },
        {
          weight: 2,
          attribute: 'SeriesDescription',
          constraint: {
            doesNotContain: {
              value: 'Uncorrected',
            },
          },
        },

        // Should we check if CorrectedImage contains ATTN?
        // (0028,0051) (CorrectedImage): NORM\DTIM\ATTN\SCAT\RADL\DECY
      ],
      // Can be used to select matching studies
      // studyMatchingRules: [],
    },
    chartDisplaySet: {
      // Unused currently
      imageMatchingRules: [],
      // Matches displaysets, NOT series
      seriesMatchingRules: [
        {
          attribute: 'Modality',
          constraint: {
            equals: {
              value: 'CHT',
            },
          },
          required: true,
        },
      ],
    },
  },
  stages: [
    {
      id: 'dataPreparation',
      name: 'Data Preparation',
      viewportStructure: {
        layoutType: 'grid',
        properties: {
          rows: 1,
          columns: 3,
        },
      },
      viewports: [...getPTViewports()],
      createdDate: '2023-01-01T00:00:00.000Z',
    },

    {
      id: 'registration',
      name: 'Registration',
      viewportStructure: {
        layoutType: 'grid',
        properties: {
          rows: 3,
          columns: 3,
        },
      },
      viewports: [...getFusionViewports(), ...getCTViewports(), ...getPTViewports()],
      createdDate: '2023-01-01T00:00:00.000Z',
    },

    {
      id: 'roiQuantification',
      name: 'ROI Quantification',
      viewportStructure: {
        layoutType: 'grid',
        properties: {
          rows: 1,
          columns: 3,
        },
      },
      viewports: [...getFusionViewports()],
      createdDate: '2023-01-01T00:00:00.000Z',
    },

    {
      id: 'kineticAnalysis',
      name: 'Kinetic Analysis',
      viewportStructure: {
        layoutType: 'grid',
        properties: {
          rows: 2,
          columns: 3,
          layoutOptions: [
            {
              x: 0,
              y: 0,
              width: 1 / 3,
              height: 1 / 2,
            },
            {
              x: 1 / 3,
              y: 0,
              width: 1 / 3,
              height: 1 / 2,
            },
            {
              x: 2 / 3,
              y: 0,
              width: 1 / 3,
              height: 1 / 2,
            },
            {
              x: 0,
              y: 1 / 2,
              width: 1,
              height: 1 / 2,
            },
          ],
        },
      },
      viewports: [...getFusionViewports(), getSeriesChartViewport()],
      createdDate: '2023-01-01T00:00:00.000Z',
    },
  ],
};

/**
 * HangingProtocolModule should provide a list of hanging protocols that will be
 * available in OHIF for Modes to use to decide on the structure of the viewports
 * and also the series that hung in the viewports. Each hanging protocol is defined by
 * { name, protocols}. Examples include the default hanging protocol provided by
 * the default extension that shows 2x2 viewports.
 */

function getHangingProtocolModule() {
  return [
    {
      name: defaultProtocol.id,
      protocol: defaultProtocol,
    },
  ];
}

export default getHangingProtocolModule;
