*
* This is version 0.5.3
*
*The MIT License (MIT)
*
*Copyright (c) 2021 Benjamin Weisheit
*
*Permission is hereby granted, free of charge, to any person obtaining a copy
*of this software and associated documentation files (the "Software"), to deal
*in the Software without restriction, including without limitation the rights
*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*copies of the Software, and to permit persons to whom the Software is
*furnished to do so, subject to the following conditions:
*
*The above copyright notice and this permission notice shall be included in all
*copies or substantial portions of the Software.
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*SOFTWARE.

REPORT zi_abap_to_codecharta.

CLASS lcl_code_metrics DEFINITION.
  PUBLIC SECTION.
    METHODS run
      IMPORTING
        selection_variant TYPE variant
      RETURNING
        VALUE(result)     TYPE ztti_a2cc_code_metrics
      RAISING
        cx_salv_bs_sc_runtime_info.
  PRIVATE SECTION.
    METHODS set_alv_runtime_info.
    METHODS submit_code_metrics_report
      IMPORTING
        selection_variant TYPE variant.
    METHODS get_alv_list_from_report
      RETURNING
        VALUE(result) TYPE ztti_a2cc_code_metrics
      RAISING
        cx_salv_bs_sc_runtime_info.
ENDCLASS.

CLASS lcl_code_metrics IMPLEMENTATION.
  METHOD run.
    set_alv_runtime_info( ).
    submit_code_metrics_report( selection_variant ).
    result = get_alv_list_from_report( ).
  ENDMETHOD.

  METHOD get_alv_list_from_report.
    FIELD-SYMBOLS <alv_list>   TYPE STANDARD TABLE.
    DATA alv_list              TYPE REF TO data.
    cl_salv_bs_runtime_info=>get_data_ref( IMPORTING r_data = alv_list ).
    ASSIGN alv_list->* TO <alv_list>.
    MOVE-CORRESPONDING <alv_list> TO result.
  ENDMETHOD.

  METHOD submit_code_metrics_report.
    SUBMIT /sdf/cd_custom_code_metric
    USING SELECTION-SET selection_variant
    EXPORTING LIST TO MEMORY
    AND RETURN.
  ENDMETHOD.

  METHOD set_alv_runtime_info.
    cl_salv_bs_runtime_info=>set(
      EXPORTING display  = abap_false
                metadata = abap_false
                data     = abap_true ).
  ENDMETHOD.
ENDCLASS.

CLASS lcl_input_screen DEFINITION.
  PUBLIC SECTION.
    METHODS check_file_directory
      IMPORTING
        file TYPE localfile.
    METHODS check_variant
      IMPORTING
        variant TYPE variant.
ENDCLASS.

CLASS lcl_input_screen IMPLEMENTATION.
  METHOD check_file_directory.
    DATA directory TYPE localfile.
    CALL FUNCTION 'LIST_SPLIT_PATH'
      EXPORTING
        filename = file
      IMPORTING
        pathname = directory.
    CALL FUNCTION 'PFL_CHECK_DIRECTORY'
      EXPORTING
        directory_long              = directory
      EXCEPTIONS
        pfl_dir_not_exist           = 1
        pfl_permission_denied       = 2
        pfl_cant_build_dataset_name = 3
        pfl_file_not_exist          = 4
        pfl_authorization_missing   = 5
        OTHERS                      = 6.
    IF sy-subrc <> 0.
      CASE sy-subrc.
        WHEN 1.
          MESSAGE 'Directory does not exist on the appserver'(002) TYPE 'E'.
        WHEN 2 OR 5.
          MESSAGE 'No permission to the directory on the appserver'(003) TYPE 'E'.
        WHEN OTHERS.
          MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
                     WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ENDCASE.
    ENDIF.
  ENDMETHOD.

  METHOD check_variant.
    SELECT SINGLE variant INTO @DATA(exists) FROM varid
        WHERE report EQ '/SDF/CD_CUSTOM_CODE_METRIC'
          AND variant EQ @variant.
    IF sy-subrc IS NOT INITIAL.
      MESSAGE 'Variant not defined for Code Metrics in tx /SDF/CD_CCA'(001) TYPE 'E'.
    ENDIF.
  ENDMETHOD.
ENDCLASS.

CLASS lcl_file_output DEFINITION.
  PUBLIC SECTION.
    METHODS write_file
      IMPORTING
        VALUE(file_name) TYPE localfile
        json             TYPE string.
  PRIVATE SECTION.
    METHODS convert_string_to_xstring
      IMPORTING
        string        TYPE string
      RETURNING
        VALUE(result) TYPE xstring.
    METHODS write_xstring_to_file
      IMPORTING
        file_name TYPE localfile
        xstring   TYPE xstring.
    METHODS adjust_filename
      IMPORTING
        file_name     TYPE localfile
      RETURNING
        VALUE(result) TYPE localfile.
ENDCLASS.

CLASS lcl_file_output IMPLEMENTATION.
  METHOD write_file.
    write_xstring_to_file(
        file_name = adjust_filename( file_name )
        xstring   = convert_string_to_xstring( json ) ).
  ENDMETHOD.
  METHOD write_xstring_to_file.
    OPEN DATASET file_name FOR OUTPUT IN BINARY MODE.
    IF sy-subrc NE 0.
      WRITE : / 'Error Opening the Server Filepath :', file_name.
    ELSE.
      TRANSFER xstring TO file_name.
      CLOSE DATASET file_name.
      WRITE : / 'File Downloaded to the Server at :', file_name.
    ENDIF.
  ENDMETHOD.

  METHOD convert_string_to_xstring.
    CALL FUNCTION 'SCMS_STRING_TO_XSTRING'
      EXPORTING
        text   = string
      IMPORTING
        buffer = result.
  ENDMETHOD.

  METHOD adjust_filename.
    result = file_name.
    REPLACE ALL OCCURRENCES OF '<DATE>' IN result WITH sy-datum.
  ENDMETHOD.
ENDCLASS.

PARAMETERS varnt TYPE variant.
PARAMETERS file TYPE localfile.

SELECTION-SCREEN BEGIN OF BLOCK d WITH FRAME TITLE TEXT-bld.
PARAMETERS agg_modl TYPE abap_bool RADIOBUTTON GROUP agg DEFAULT 'X'.
PARAMETERS agg_devc TYPE abap_bool RADIOBUTTON GROUP agg.
SELECTION-SCREEN END OF BLOCK d.

SELECTION-SCREEN BEGIN OF BLOCK a WITH FRAME TITLE TEXT-bla.
PARAMETERS dpndncy TYPE abap_bool RADIOBUTTON GROUP dpn DEFAULT 'X'.
PARAMETERS wo_dpnd TYPE abap_bool RADIOBUTTON GROUP dpn.
PARAMETERS cycls TYPE abap_bool RADIOBUTTON GROUP dpn.
SELECTION-SCREEN END OF BLOCK a.

AT SELECTION-SCREEN.
  DATA(input_screen) = NEW lcl_input_screen( ).
  input_screen->check_file_directory( file ).
  input_screen->check_variant( varnt ).

START-OF-SELECTION.
  DATA(code_metrics) = NEW lcl_code_metrics( )->run( varnt ).

  DATA(abap2codecharta) = zcl_i_a2cc_factory=>create( COND #( WHEN agg_devc = abap_true
                                                              THEN zcl_i_a2cc_factory=>aggregation_levels-package
                                                              ELSE zcl_i_a2cc_factory=>aggregation_levels-class ) ).

  DATA(json) = abap2codecharta->to_json( metrics               = code_metrics
                                         analyze_dependecies   = dpndncy
                                         analyze_direct_cycles = cycls ).

  NEW lcl_file_output( )->write_file( file_name = file
                                      json      = json ).
