package com.volcengine.reactnative.veplayer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.ss.ttvideoengine.TTVideoEngine;
import com.ss.ttvideoengine.model.BareVideoInfo;
import com.ss.ttvideoengine.model.BareVideoModel;
import com.ss.ttvideoengine.model.IVideoModel;
import com.ss.ttvideoengine.model.VideoInfo;
import com.ss.ttvideoengine.Resolution;
import com.ss.ttvideoengine.model.VideoRef;
import com.ss.ttvideoengine.source.VideoModelSource;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

// video data Model
public class VideoModelImpl {
    private final static String TAG = "VideoModelImpl";
    
    /**
     * id of video res
     */
    public String videoId;
    /**
     * duration of video res
     */
    public long durationInS;
    /**
     * resolution list of video resource
     */
    public List<StreamItem> streamItems;

    /**
     * Default constructor
     */
    public VideoModelImpl() {
        this.streamItems = new ArrayList<>();
    }

    /**
     * Constructor with JSONObject
     * @param obj JSONObject containing video model data
     */
    public VideoModelImpl(@NonNull JSONObject obj) {
        this.streamItems = new ArrayList<>();
        
        // Parse videoId
        this.videoId = obj.optString("videoId", "");
        
        // Parse durationInS
        this.durationInS = obj.optLong("durationInS", 0);
        
        // Parse streamItems
        if (obj.has("streamItems")) {
            JSONArray jsonStreamItems = obj.optJSONArray("streamItems");
            if (jsonStreamItems != null) {
                for (int i = 0; i < jsonStreamItems.length(); i++) {
                    JSONObject jsonStreamItem = jsonStreamItems.optJSONObject(i);
                    if (jsonStreamItem != null) {
                        StreamItem streamItem = new VideoModelImpl.StreamItem(jsonStreamItem);
                        this.streamItems.add(streamItem);
                    }
                }
            }
        }
    }

    /**
     * Constructor with individual parameters
     * @param videoId video id
     * @param durationInS duration in seconds
     * @param streamItems list of stream items
     */
    public VideoModelImpl(String videoId, long durationInS, List<StreamItem> streamItems) {
        this.videoId = videoId;
        this.durationInS = durationInS;
        this.streamItems = streamItems != null ? streamItems : new ArrayList<>();
    }

    /**
     * Convert to JSONObject
     * @return JSONObject representation of this VideoModelImpl
     */
    @Nullable
    public JSONObject toJson() {
        try {
            JSONObject jsonObj = new JSONObject();
            jsonObj.put("videoId", this.videoId);
            jsonObj.put("durationInS", this.durationInS);
            
            JSONArray streamItemsArray = new JSONArray();
            for (StreamItem streamItem : this.streamItems) {
                JSONObject streamItemJson = streamItem.toJson();
                if (streamItemJson != null) {
                    streamItemsArray.put(streamItemJson);
                }
            }
            jsonObj.put("streamItems", streamItemsArray);
            
            return jsonObj;
        } catch (JSONException e) {
            return null;
        }
    }

    @Override
    public String toString() {
        JSONObject jsonObj = toJson();
        return jsonObj != null ? jsonObj.toString() : super.toString();
    }

  public static IVideoModel createVideoModel(VideoModelImpl videoModel) {
     List<VideoInfo> videoInfos = new ArrayList<>();
     for (StreamItem streamItem : videoModel.streamItems) {
         videoInfos.add(new BareVideoInfo
                 .Builder()
                 .mediaType(VideoRef.TYPE_VIDEO)
                 .urls(Arrays.asList(streamItem.url))
                 .fileHash(streamItem.cacheKey)
                 .bitrate(streamItem.bitrate)
                 .resolution(streamItem.resolution)
                 .vWidth(streamItem.width)
                 .vHeight(streamItem.height)
                 .format(streamItem.format)
                 .codecType(streamItem.codecType)
                 .spadea(streamItem.playAuth)
                 .build());
     }
     return (IVideoModel) new BareVideoModel.Builder()
             .duration(videoModel.durationInS)
             .vid(videoModel.videoId) 
             .setVideoInfos(videoInfos) 
             .adaptive(true)
             .dynamicType(TTVideoEngine.DYNAMIC_TYPE_SEGMENTBASE)
             .build();
 }

  public static VideoModelSource createVideoModelSource(VideoModelImpl videoModel, Resolution resolution) {
     IVideoModel _videoModel = createVideoModel(videoModel);
     // build video model source     
     final VideoModelSource.Builder builder = new VideoModelSource.Builder()
             .setVid(_videoModel.getVideoRefStr(VideoRef.VALUE_VIDEO_REF_VIDEO_ID))
             .setVideoModel(_videoModel);
     
     if (resolution != null) {
         builder.setResolution(resolution);
     }
     
     return builder.build();
 }

  /**
   * Create VideoModelSource without resolution parameter
   * @param videoModel the video model
   * @return VideoModelSource instance
   */
  public static VideoModelSource createVideoModelSource(VideoModelImpl videoModel) {
     return createVideoModelSource(videoModel, null);
  }

  public static class StreamItem {
        /**
         * url of video file
         */
        public String url;
        /**
         * unique id of video file
         */
        public String cacheKey;
        /**
         * encode type of video. 
         * one of: h264、h265
         */
        public String codecType;
        
        /**
         * format type of video file. 
         * one of: dash、hls、mp4
         */
        public String format;
        
        /**
         * width of video
         */
        public int width;
        /**
         * height of video
         */
        public int height;
        /**
         * bitrate of video in bps
         */
        public int bitrate;
        /**
         * Resolution of stream item
         */
        public Resolution resolution;
        
        /**
         * Private DRM key
         */
        public String playAuth;

        /**
         * Default constructor
         */
        public StreamItem() {
        }

        /**
         * Constructor with JSONObject
         * @param obj JSONObject containing stream item data
         */
        public StreamItem(@NonNull JSONObject obj) {
            this.url = obj.optString("url", "");
            this.cacheKey = obj.optString("cacheKey", "");
            this.codecType = obj.optString("codecType", "");
            this.format = obj.optString("format", "");
            this.width = obj.optInt("width", 0);
            this.height = obj.optInt("height", 0);
            this.bitrate = obj.optInt("bitrate", 0);
            this.playAuth = obj.optString("playAuth", "");
            
            // Parse resolution if present - resolution is an integer index mapping to Resolution enum
            if (obj.has("resolution")) {
                try {
                    int resolutionIndex = obj.optInt("resolution", 0);
                    this.resolution = Resolution.valueOf(resolutionIndex);
                } catch (Exception e) {
                    // Resolution parsing failed, leave as null
                    this.resolution = null;
                }
            }
        }

        /**
         * Constructor with individual parameters
         */
        public StreamItem(String url, String cacheKey, String codecType, String format, 
                         int width, int height, int bitrate, Resolution resolution, String playAuth) {
            this.url = url;
            this.cacheKey = cacheKey;
            this.codecType = codecType;
            this.format = format;
            this.width = width;
            this.height = height;
            this.bitrate = bitrate;
            this.resolution = resolution;
            this.playAuth = playAuth;
        }

        /**
         * Convert to JSONObject
         * @return JSONObject representation of this StreamItem
         */
        @Nullable
        public JSONObject toJson() {
            try {
                JSONObject jsonObj = new JSONObject();
                jsonObj.put("url", this.url);
                jsonObj.put("cacheKey", this.cacheKey);
                jsonObj.put("codecType", this.codecType);
                jsonObj.put("format", this.format);
                jsonObj.put("width", this.width);
                jsonObj.put("height", this.height);
                jsonObj.put("bitrate", this.bitrate);
                jsonObj.put("playAuth", this.playAuth);
                
                if (this.resolution != null) {
                    // Serialize resolution as integer index
                    jsonObj.put("resolution", this.resolution.getIndex());
                }
                
                return jsonObj;
            } catch (JSONException e) {
                return null;
            }
        }

        @Override
        public String toString() {
            JSONObject jsonObj = toJson();
            return jsonObj != null ? jsonObj.toString() : super.toString();
        }
    }
}

 