package com.amediamanager.config;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.elastictranscoder.AmazonElasticTranscoder;
import com.amazonaws.services.elastictranscoder.model.AudioParameters;
import com.amazonaws.services.elastictranscoder.model.CreatePipelineRequest;
import com.amazonaws.services.elastictranscoder.model.CreatePipelineResult;
import com.amazonaws.services.elastictranscoder.model.CreatePresetRequest;
import com.amazonaws.services.elastictranscoder.model.CreatePresetResult;
import com.amazonaws.services.elastictranscoder.model.Notifications;
import com.amazonaws.services.elastictranscoder.model.Thumbnails;
import com.amazonaws.services.elastictranscoder.model.VideoParameters;
import com.amediamanager.config.ConfigurationSettings.ConfigProps;

@Component
public class ElasticTranscoderPipelineResource implements ProvisionableResource {
    private static final Logger LOG = LoggerFactory.getLogger(ElasticTranscoderPipelineResource.class);
    private volatile ProvisionState state = ProvisionState.UNPROVISIONED;

    @Autowired
    private ConfigurationSettings config;

    @Autowired
    private AmazonElasticTranscoder transcoderClient;

    @PostConstruct
    public void init() {
        if (getPipeline() != null && getPreset() != null) {
            state = ProvisionState.PROVISIONED;
        }
    }

    @Override
    public ProvisionState getState() {
        return state;
    }

    @Override
    public String getName() {
        return "Elastic Transcoder Pipeline";
    }

    private String getPipeline() {
        return config.getProperty(ConfigProps.TRANSCODE_PIPELINE);
    }

    private String getPreset() {
        return config.getProperty(ConfigProps.TRANSCODE_PRESET);
    }

    private String provisionPipeline() {
        String pipelineId = config.getProperty(ConfigProps.TRANSCODE_PIPELINE);

        if (pipelineId == null) {
            state = ProvisionState.PROVISIONING;
            Notifications notifications = new Notifications()
                .withError(config.getProperty(ConfigProps.TRANSCODE_TOPIC))
                .withCompleted(config.getProperty(ConfigProps.TRANSCODE_TOPIC))
                .withProgressing("")
                .withWarning("");

            CreatePipelineRequest pipelineRequest = new CreatePipelineRequest()
                .withName("amm-reinvent-pipeline-" + UUID.randomUUID().toString().replace("-", "").substring(0, 18).toUpperCase())
                .withRole(config.getProperty(ConfigProps.TRANSCODE_ROLE))
                .withInputBucket(config.getProperty(ConfigProps.S3_UPLOAD_BUCKET))
                .withOutputBucket(config.getProperty(ConfigProps.S3_UPLOAD_BUCKET))
                .withNotifications(notifications);

            try {
                CreatePipelineResult pipelineResult = transcoderClient.createPipeline(pipelineRequest);
                pipelineId = pipelineResult.getPipeline().getId();
                config.getConfigurationProvider().persistNewProperty(ConfigProps.TRANSCODE_PIPELINE, pipelineId);
            } catch (AmazonServiceException e) {
                LOG.error("Failed creating pipeline {}", pipelineRequest.getName(), e);
                state = ProvisionState.UNPROVISIONED;
            }
        }
        return pipelineId;
    }

    private String provisionPreset() {
        String presetId = config.getProperty(ConfigProps.TRANSCODE_PRESET);

        if (presetId == null) {
            state = ProvisionState.PROVISIONING;
            Map<String, String> codecOptions = new HashMap<String, String>();
            codecOptions.put("Profile", "main");
            codecOptions.put("Level", "3.1");
            codecOptions.put("MaxReferenceFrames", "3");

            VideoParameters video = new VideoParameters()
                .withCodec("H.264")
                .withCodecOptions(codecOptions)
                .withKeyframesMaxDist("90")
                .withFixedGOP("false")
                .withBitRate("2200")
                .withFrameRate("30")
                .withMaxWidth("1280")
                .withMaxHeight("720")
                .withSizingPolicy("ShrinkToFit")
                .withPaddingPolicy("NoPad")
                .withDisplayAspectRatio("auto");

            AudioParameters audio = new AudioParameters()
                .withCodec("AAC")
                .withSampleRate("44100")
                .withBitRate("160")
                .withChannels("2");

            Thumbnails thumbnails = new Thumbnails()
                .withFormat("png")
                .withInterval("60")
                .withMaxWidth("500")
                .withMaxHeight("300")
                .withSizingPolicy("ShrinkToFit")
                .withPaddingPolicy("NoPad");

            CreatePresetRequest presetRequest = new CreatePresetRequest()
                .withName("amm-reinvent-preset-" + UUID.randomUUID().toString().replace("-", "").substring(0, 20).toUpperCase())
                .withDescription("Preset used by aMediaManager re:Invent 2013")
                .withContainer("mp4")
                .withVideo(video)
                .withAudio(audio)
                .withThumbnails(thumbnails);

            try {
                CreatePresetResult result = transcoderClient.createPreset(presetRequest);
                presetId = result.getPreset().getId();
                config.getConfigurationProvider().persistNewProperty(ConfigProps.TRANSCODE_PRESET, presetId);
            } catch (AmazonServiceException e) {
                LOG.error("Failed creating transcoder preset {}", presetRequest.getName(), e);
                state = ProvisionState.UNPROVISIONED;
            }
        }
        return presetId;
    }

    @Override
    public synchronized void provision() {
        if (provisionPipeline() != null && provisionPreset() != null) {
            state = ProvisionState.PROVISIONED;
        }
    }
}

@@ -1523,24 +1523,101 @@
 ) %7B%0A        
+getState();%0A    %7D%0A%0A    @Override%0A    public ProvisionState getState() %7B%0A    %09
 if (getPipel
@@ -1722,72 +1722,9 @@
     
-%7D%0A%0A    @Override%0A    public ProvisionState getState() %7B%0A        
+%09
 retu
@@ -2199,32 +2199,81 @@
 neId == null) %7B%0A
+        %09LOG.info(%22Provisioning ETS Pipeline.%22);%0A
             stat
@@ -3280,32 +3280,132 @@
 line().getId();%0A
+                LOG.info(%22Pipeline %7B%7D created. Persisting to configuration provider.%22, pipelineId);%0A
                 
@@ -3891,32 +3891,79 @@
 etId == null) %7B%0A
+        %09LOG.info(%22Provisioning ETS Preset.%22);%0A
             stat
@@ -5948,24 +5948,120 @@
  presetId);%0A
+                LOG.info(%22Preset %7B%7D created. Persisting to configuration provider.%22, presetId);%0A
             

Test provisioned status each time.