//
//  rhimportd
//
//  The Radio Helsinki Rivendell Import Daemon
//
//
//  Copyright (C) 2015-2016 Christian Pointner <equinox@helsinki.at>
//
//  This file is part of rhimportd.
//
//  rhimportd is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  any later version.
//
//  rhimportd is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with rhimportd. If not, see <http://www.gnu.org/licenses/>.
//

package main

import (
	"encoding/json"
	"fmt"
	"html"
	"net/http"

	"code.helsinki.at/rhrd-go/rddb"
	"code.helsinki.at/rhrd-go/rhimport"
)

type webSimpleRequestData struct {
	UserName           string `json:"LOGIN_NAME"`
	Password           string `json:"PASSWORD"`
	ShowId             uint   `json:"SHOW_ID"`
	ClearShowCarts     bool   `json:"CLEAR_SHOW_CARTS"`
	MusicPoolGroup     string `json:"MUSIC_POOL_GROUP"`
	Cart               uint   `json:"CART_NUMBER"`
	ClearCart          bool   `json:"CLEAR_CART"`
	Cut                uint   `json:"CUT_NUMBER"`
	Channels           uint   `json:"CHANNELS"`
	NormalizationLevel int    `json:"NORMALIZATION_LEVEL"`
	AutotrimLevel      int    `json:"AUTOTRIM_LEVEL"`
	UseMetaData        bool   `json:"USE_METADATA"`
	SourceUri          string `json:"SOURCE_URI"`
}

func newWebSimpleRequestData(conf *rhimport.Config) *webSimpleRequestData {
	rd := new(webSimpleRequestData)
	rd.UserName = ""
	rd.Password = ""
	rd.ShowId = 0
	rd.ClearShowCarts = false
	rd.MusicPoolGroup = ""
	rd.Cart = 0
	rd.ClearCart = false
	rd.Cut = 0
	rd.Channels = conf.ImportParamDefaults.Channels
	rd.NormalizationLevel = conf.ImportParamDefaults.NormalizationLevel
	rd.AutotrimLevel = conf.ImportParamDefaults.AutotrimLevel
	rd.UseMetaData = conf.ImportParamDefaults.UseMetaData
	rd.SourceUri = ""

	return rd
}

type webSimpleResponseData struct {
	ResponseCode int    `json:"RESPONSE_CODE"`
	ErrorString  string `json:"ERROR_STRING"`
	Cart         uint   `json:"CART_NUMBER"`
	Cut          uint   `json:"CUT_NUMBER"`
}

func webSimpleErrorResponse(w http.ResponseWriter, code int, errStr string) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusInternalServerError)
	encoder := json.NewEncoder(w)
	respdata := webSimpleResponseData{code, errStr, 0, 0}
	encoder.Encode(respdata)
}

func webSimpleResponse(w http.ResponseWriter, result *rhimport.Result) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusInternalServerError)
	encoder := json.NewEncoder(w)
	respdata := webSimpleResponseData{result.ResponseCode, result.ErrorString, result.Cart, result.Cut}
	encoder.Encode(respdata)
}

func webSimpleParseRequest(conf *rhimport.Config, trusted bool, r *http.Request) (ctx *rhimport.Context, err error) {
	decoder := json.NewDecoder(r.Body)
	reqdata := newWebSimpleRequestData(conf)
	if jsonerr := decoder.Decode(reqdata); jsonerr != nil {
		err = fmt.Errorf("Error parsing JSON response: %s", jsonerr)
		return
	}

	ctx = rhimport.NewContext(conf, nil, getStdLog("sess-%s-std"), getDbgLog("sess-%s-dbg"))
	if trusted {
		ctx.UserName = r.Header.Get("X-Forwarded-User")
	} else {
		ctx.UserName = reqdata.UserName
		ctx.Password = reqdata.Password
	}
	ctx.Trusted = trusted
	ctx.ShowId = reqdata.ShowId
	ctx.ClearShowCarts = reqdata.ClearShowCarts
	ctx.GroupName = reqdata.MusicPoolGroup
	ctx.Cart = reqdata.Cart
	ctx.ClearCart = reqdata.ClearCart
	ctx.Cut = reqdata.Cut
	ctx.Channels = reqdata.Channels
	ctx.NormalizationLevel = reqdata.NormalizationLevel
	ctx.AutotrimLevel = reqdata.AutotrimLevel
	ctx.UseMetaData = reqdata.UseMetaData
	ctx.SourceUri = reqdata.SourceUri
	return
}

func webSimpleDone(res rhimport.Result, userdata interface{}) bool {
	c := userdata.(chan<- rhimport.Result)
	c <- res
	return true
}

func webSimpleHandler(conf *rhimport.Config, db *rddb.DB, sessions *rhimport.SessionStore, trusted bool, w http.ResponseWriter, r *http.Request) {
	rhdl.Printf("WebSimpleHandler: %s requests '%s'", r.RemoteAddr, html.EscapeString(r.URL.Path))

	var ctx *rhimport.Context
	var err error
	if ctx, err = webSimpleParseRequest(conf, trusted, r); err != nil {
		webSimpleErrorResponse(w, http.StatusBadRequest, err.Error())
		return
	}

	_, s, code, errstring := sessions.New(ctx, "")
	if code != http.StatusOK {
		webSimpleErrorResponse(w, code, errstring)
		return
	}

	donechan := make(chan rhimport.Result, 1)
	if err := s.AddDoneHandler((chan<- rhimport.Result)(donechan), webSimpleDone); err != nil {
		webSimpleErrorResponse(w, http.StatusInternalServerError, err.Error())
		return
	}

	s.Run(0)
	res := <-donechan
	webSimpleResponse(w, &res)
	return
}