<template>
  <div id="app">
    <div class="wrapper">
      <div class="container">
        <aside id="panel">
          <div class="header">
            <button class="btn btn-primary btn-circle"><i class="fa fa-angle-left"></i></button>
            <h2>SquiggleCam</h2>
          </div>

          <image-chooser @selected="onInputSelected"></image-chooser>

          <div class="image-upload" v-if="this.inputType === 'upload'">
            <croppa v-model="myCroppa" :width="250" :height="250" :preventWhiteSpace="true" :quality="2"></croppa>
            <button @click="uploadCroppedImage">Output JPEG</button>
          </div>

          <div class="image-webcam" v-if="this.inputType === 'webcam'">
            <div class="video-controls">
              <select v-model="webcam.camera">
                <option>- Select Device: -</option>
                <option v-for="device in webcam.devices"
                        :key="device.deviceId"
                        :value="device.deviceId">{{ device.label }}</option>
              </select>
              <button v-if="webcam.streaming"
                      type="button"
                      class="btn btn-sm"
                      @click="onStop"><svg width="12" height="12"><rect width="12" height="12" style="fill:rgb(255,0,0)" />
              </svg></button>
              <button type="button"
                      class="btn btn-sm"
                      v-if="!webcam.streaming"
                      @click="onStart">Start</button>
            </div>

            <webcam ref="webcam"
                    :device-id="webcam.deviceId"
                    :width="settings.width"
                    :height="settings.height"
                    @started="onStarted"
                    @stopped="onStopped"
                    @error="onError"
                    @cameras="onCameras"
                    @camera-change="onCameraChange" />

            <button type="button"
                    class="btn btn-record"
                    v-if="webcam.streaming"
                    @click="onCapture">
              <svg height="48" width="48" viewBox="0 0 48 48">
              <circle cx="24" cy="24" r="23" stroke="white" stroke-width="1" fill="#D41616" />
              </svg>
            </button>


          </div>

          <div class="section-title">
            Squiggle Controls:
          </div>
          <div class="slider">
        <span class="label">
          Frequency
        </span>
            <input type="range" min="5" max="256" v-model="settings.frequency">
            <div class="output">{{ settings.frequency }}</div>
          </div>
          <div class="slider">
        <span class="label">
          Line Count
        </span>
            <input type="range" min="10" max="200" v-model="settings.lineCount">
            <div class="output">{{ settings.lineCount }}</div>
          </div>
          <div class="slider">
            <span class="label">
              Amplitude
            </span>
            <input type="range" min="0.1" max="5" step="0.1" v-model="settings.amplitude">
            <div class="output">{{ settings.amplitude }}</div>
          </div>

          <div class="slider">
            <span class="label">
              Smoothing
            </span>
            <input type="range" min="0" max="0.5" step="0.05" v-model="line.smoothing">
            <div class="output">{{ line.smoothing}}</div>
          </div>

          <div class="slider">
            <span class="label">
              Flattening
            </span>
            <input type="range" min="0" max="1" step="0.01" v-model="line.flattening">
            <div class="output">{{ line.flattening }}</div>
          </div>

          <div class="section-title">
            Download:
          </div>
          <div class="actions">
            <button class="btn">
              JPG
            </button>
            <button class="btn" @click="downloadSVG">
              SVG
            </button>
            <button class="btn">
              ZIP
            </button>
          </div>

        </aside>
        <main>
          <div v-if="canvasData" class="svg-container" style="padding: 10px;" ref="container">
            <svg-chart ref="svgResult" :lines="lines" :options="line" :width="settings.width" :height="settings.height"></svg-chart>
          </div>
        </main>
      </div>
    </div>
  </div>
</template>

<script>
  // import Navbar from './components/Navbar'
  // import Loader from './components/Loader'
  // import Editor from './components/Editor'
  import ImageChooser from './components/ImageChooser'
  import WebCam from './components/WebCam'
  import svgChart from './components/svgChart';

  export default {
  name: 'App',
  components: {
    //cropActions: Navbar ,
    //loader: Loader,
    //editor: Editor,
    imageChooser: ImageChooser,
    webcam: WebCam,
    svgChart: svgChart
  },
  data() {
    return {
      myCroppa: {},
      dataUrl: '',
      line: {
        smoothing: 0.25,
        flattening: 0.5
      },
      lines: [],
      inputType: "upload",
      settings: {
        frequency: 150,
        amplitude: 1,
        lineCount: 54,
        brightness: 0,
        contrast: 0,
        minBrightness: 0,
        maxBrightness: 255,
        spacing: 1,
        width: 500,
        height: 500
      },
      canvasData: null,
      webcam: {
        img: null,
        camera: null,
        deviceId: null,
        device: null,
        devices: [],
        streaming: false
      },
      // cropper: {
      //   cropped: false,
      //   cropping: false,
      //   loaded: false,
      //   name: '',
      //   previousUrl: '',
      //   type: '',
      //   url: '',
      //   croppedImageData: ''
      // },
    };
  },

  watch: {
    'webcam.camera': function(id) {
      this.webcam.deviceId = id;
    },
    'webcam.devices': function() {
      // Once we have a list select the first one
      let first = this.webcam.devices[0];
      if (first) {
        this.webcam.camera = first.deviceId;
        this.webcam.deviceId = first.deviceId;
      }
    },
    // 'cropper.croppedImageData': function(){
    //   const canvas = this.cropper.croppedImageData;
    //   const ctx = canvas.getContext("2d");
    //   this.canvasData = ctx.getImageData(0, 0, 500, 500);
    //   return true;
    // },
    'settings.frequency': function(){
      this.processImage();
    },
    'settings.lineCount': function(){
      this.processImage();
    },
    'settings.amplitude': function(){
      this.processImage();
    },
    'canvasData': function(){
      this.processImage();
    }
  },

  methods: {
    downloadSVG(){
      console.log(this.$refs.svgResult.$el.innerHTML);
    },
    uploadCroppedImage() {
      this.myCroppa.generateBlob((blob) => {
        let canvas = document.createElement("canvas");
        canvas.width = 500;
        canvas.height = 500;
        //   const ctx = canvas.getContext("2d");
        //   this.canvasData = ctx.getImageData(0, 0, 500, 500);

        const ctx = canvas.getContext('2d');
        let img = new Image();

        img.onload = () => {
          ctx.drawImage(img, 0, 0)
          this.canvasData = ctx.getImageData(0, 0, 500, 500);
        };

        img.src = URL.createObjectURL(blob);
      }, 'image/jpeg', 1)
    },
    processImage() {
      this.$worker.run((data) => {
        // Gather all necessary data from the main thread
        let config = data.config;
// context.getImageData(0, 0, config.WIDTH, config.HEIGHT);
        let imagePixels = data.image;
        let width = config.width;
        let height = config.height;

// Create some defaults for squiggle-point array
        let squiggleData = [];
        let r = 5;
        let a = 0;
        let b;
        let z;
        let currentLine = []; // create empty array for storing x,y coordinate pairs
        let currentVerticalPixelIndex = 0;
        let currentHorizontalPixelIndex = 0;
        let contrastFactor = (259 * (config.contrast + 255)) / (255 * (259 - config.contrast)); // This was established through experiments
        let horizontalLineSpacing = Math.floor(height/config.lineCount); // Number of pixels to advance in vertical direction
        //console.log(horizontalLineSpacing);

// Iterate line by line (top line to bottom line) in increments of horizontalLineSpacing
        //let tmpCounter = 0;
        for (let y = 0; y < height; y+= horizontalLineSpacing) {
          a = 0;
          currentLine = [];
          currentLine.push([0, y]); // Start the line

          currentVerticalPixelIndex = y*width;  // Because Image Pixel array is of length width * height,
                                                // starting pixel for each line will be this

          // Loop through pixels from left to right within the current line, advancing by increments of config.SPACING
          //console.log(config.spacing, width);
          for (let x = config.spacing; x < width; x += config.spacing ) {

            currentHorizontalPixelIndex = x + currentVerticalPixelIndex; // Get array position of current pixel

            // When there is contrast adjustment, the calculations of brightness values are a bit different
            if (config.contrast !== 0) {
              // Determine how bright a pixel is, from 0 to 255 by summing three channels (R,G,B) multiplied by some coefficients
              b = (0.2125 * ((contrastFactor * (imagePixels.data[4 * currentHorizontalPixelIndex] - 128) + 128 )
                + config.brightness)) + (0.7154 * ((contrastFactor * (imagePixels.data[4 * (currentHorizontalPixelIndex + 1)] - 128) + 128)
                + config.brightness)) + (0.0721 * ((contrastFactor*(imagePixels.data[4*(currentHorizontalPixelIndex+2)]-128)+128) + config.brightness));
            } else {
              b = (0.2125 * (imagePixels.data[4*currentHorizontalPixelIndex] + config.brightness)) + (0.7154 * (imagePixels.data[4*(currentHorizontalPixelIndex + 1)]+ config.brightness)) + (0.0721 * (imagePixels.data[4*(currentHorizontalPixelIndex + 2)] + config.brightness));
            }

            b = Math.max(config.minBrightness,b);    // Set minimum line curvature to value set by the user
            z = Math.max(config.maxBrightness-b,0);  // Set maximum line curvature to value set by the user

            // The magic of the script, determines how high / low the squiggle goes
            r = config.amplitude * z / config.lineCount;

            a += z / config.frequency;
            currentLine.push([x,y + Math.sin(a)*r]);
            //currentLine.push([x,y + 10 * (tmpCounter%2 ? -1 : 1)]);
            //tmpCounter++;
          }
          currentLine.push([config.width, y]);
          squiggleData.push(currentLine);
        }

        return squiggleData;
      }, [{
        config: {
          ...this.settings
        },
        image: this.canvasData
      }])
        .then(result => {
          this.lines = [];

          result.forEach( line => {
            this.lines.push({values: line});
          })
        })
        .catch(e => {
          console.error(e)
        })
    },
    onCapture() {
      this.webcam.img = this.$refs.webcam.capture();
      this.canvasData = this.$refs.webcam.getCanvasRaw();
    },
    onStarted(stream) {
      this.webcam.streaming = true;
      //console.log("On Started Event", stream);
    },
    onStopped(stream) {
      this.webcam.streaming = false;
      //console.log("On Stopped Event", stream);
    },
    onStop() {
      this.$refs.webcam.stop();
    },
    onStart() {
      this.$refs.webcam.start();
    },
    onError(error) {
      //console.log("On Error Event", error);
    },
    onCameras(cameras) {
      this.webcam.devices = cameras;
      //console.log("On Cameras Event", cameras);
    },
    onCameraChange(deviceId) {
      this.webcam.deviceId = deviceId;
      this.webcam.camera = deviceId;
      //console.log("On Camera Change Event", deviceId);
    },
    change(action) {
      const editor = this.$refs.editor;
      switch (action) {
        case 'crop':
          editor.crop();
          break;
        case 'clear':
          editor.clear();
          break;
        case 'restore':
          editor.restore();
          break;
        case 'remove':
          editor.reset();
          break;
        default:
      }
    },
    onInputSelected(type) {
      this.inputType = type;
    }
  }
}
</script>

<style lang="scss">
  @import './styles/index.scss';

  /*.cropper-header {*/
    /*background-color: #666;*/
    /*height: 3rem;*/
    /*overflow: hidden;*/
    /*padding-left: 1rem;*/
    /*padding-right: 1rem;*/
    /*position: relative;*/
    /*z-index: 1;*/
  /*}*/
  /*@media (min-width: 768px) {*/
    /*.cropper-header {*/
      /*padding-left: 1.5rem;*/
      /*padding-right: 1.5rem;*/
    /*}*/
  /*}*/
  .title {
    color: #fff;
    display: block;
    float: left;
    font-size: 1.125rem;
    line-height: 3rem;
  }
</style>
