class MediaItemEntityDataMapper {

    public static MediaItemEntity transform( ProgramEntity programEntity ) {
        Log.i( TAG, "transform : programEntity=" + programEntity.toString() );

        boolean dateValidationError = false, recordedIdValidationError = false;
        List<ErrorEntity> errors = new ArrayList<>();

        Log.i( TAG, "transform : startTs=" + programEntity.recording().startTs() + ", test=" + ( null == programEntity.recording().startTs() ) );
        if( null == programEntity.recording().startTs() ) {
            Log.i( TAG, "transform : added StartTs to errors" );
            errors.add( ErrorEntity.create( "StartTs", "StartTs is not valid for " + programEntity.title() + " - " + programEntity.subTitle(), -1 ) );
            dateValidationError = true;
        }

        if( null == programEntity.recording().endTs() ) {
            errors.add( ErrorEntity.create( "EndTs", "EndTs is not valid for " + programEntity.title() + " - " + programEntity.subTitle(), -1 ) );
            dateValidationError = true;
        }

        if( programEntity.recording().status() != -1 && ( programEntity.recording().recordedId().equals( "" ) || programEntity.recording().recordedId().equals( "0" )  ) ) {
            errors.add( ErrorEntity.create( "RecordedId", "Recorded Id is not valid for " + programEntity.title() + " - " + programEntity.subTitle(), -1 ) );
            recordedIdValidationError = true;
        }

//        if( !recordedIdValidationError ) {
//            mediaItem.setId( programEntity.recording().translateRecordedId() );
//        }

        Media media = null;
        String url = null, contentType = null, previewUrl = null, recordingGroup = null, updateSavedBookmarkUrl = null;
        int percentComplete = 0, liveStreamId = 0;
        boolean watched = false, recording = false;
        long bookmark = 0, duration = 0;
        switch( programEntity.recording().status() ) {

            case -3 :
            case -2 :

                url = "/Content/GetFile?FileName=" + programEntity.fileName();
                if( null != programEntity.getLiveStreamInfoEntity() ) {

                    url = programEntity.getLiveStreamInfoEntity().relativeUrl();
                    percentComplete = programEntity.getLiveStreamInfoEntity().percentComplete();
                    liveStreamId = programEntity.getLiveStreamInfoEntity().id();

                }

                media = Media.PROGRAM;
                contentType = setContentType( url );
                if( !recordedIdValidationError ) {
                    previewUrl = "/Content/GetPreviewImage?RecordedId=" + programEntity.recording().recordedId();
                }

                watched = ( programEntity.programFlags() & 0x00000200 ) > 0;

                recording = programEntity.recording().status() == -2;

                recordingGroup = programEntity.recording().recGroup();

                break;

            case -1 :

                media = Media.UPCOMING;

                break;

            default :

                break;

        }

        if( !dateValidationError ) {
            duration = calculateDuration( programEntity.recording().startTs(), programEntity.recording().endTs() );
        }

        Map<String, String> artworks = defaultArtworks();
        if( null != programEntity.artwork() && null != programEntity.artwork().artworkInfos() && !programEntity.artwork().artworkInfos().isEmpty() ) {

            artworks = addArtwork( programEntity.artwork().artworkInfos() );

        }

        if( null != programEntity.getLiveStreamInfoEntity() ) {

            liveStreamId = programEntity.getLiveStreamInfoEntity().id();

        }

        List<String> castMembers = new ArrayList<>();
        List<String> characters = new ArrayList<>();

        if( null != programEntity.cast() && null != programEntity.cast().castMembers() && !programEntity.cast().castMembers().isEmpty() ) {

            for( CastMemberEntity castMember : programEntity.cast().castMembers() ) {

                if( !castMembers.contains( castMember.name() ) ) {
                    castMembers.add( castMember.name() );
                }

                if( !characters.contains( castMember.characterName() ) ) {
                    characters.add( castMember.characterName() );
                }

            }

        }

        String cast = "";
        if( !castMembers.isEmpty() ) {

            StringBuilder sb = new StringBuilder();
            for( String name : castMembers ) {
                sb.append( name ).append( ' ' );
            }

            cast = sb.toString().trim();

        }

        String characterNames = "";
        if( !characters.isEmpty() ) {

            StringBuilder sb = new StringBuilder();
            for( String name : characters ) {
                sb.append( name ).append( ' ' );
            }

            characterNames = sb.toString().trim();

        }

        if( !recordedIdValidationError ) {
            updateSavedBookmarkUrl = String.format( "/Dvr/SetSavedBookmark?RecordedId=%s1", String.valueOf( programEntity.recording().recordedId() ) );
        }
        bookmark = programEntity.getBookmark();

        Log.i( TAG, "transform : exit" );
        return MediaItemEntity.create(
                programEntity.recording().translateRecordedId(), media, programEntity.title(),
                programEntity.subTitle(), programEntity.description(), programEntity.startTime(),
                programEntity.programFlags(), programEntity.season(), programEntity.episode(),
                programEntity.channel().callSign(), cast.trim(), characterNames, url, artworks.get( FANART_KEY ),
                artworks.get( COVERART_KEY ), artworks.get( BANNER_KEY ), previewUrl, contentType, duration,
                percentComplete, recording, liveStreamId,
                watched, updateSavedBookmarkUrl, bookmark,
                programEntity.inetref(), null, -1, recordingGroup, errors );
    }

    private  MediaItemEntityDataMapper();

}