func writeProject(s session.Store, projectName string, fileType string, fileName string, codeFile string, timeStamp int64, resourceFiles []string, image string, alternateFile string, alternateType string, commit string) Data {

	// if user is not logged in return
	userName := ""
	if s.Get("UserName") != nil {
		userName = s.Get("UserName").(string)
	}
	if userName == "" {
		beego.Error("No user name available.")
		return Data{}
	}
	if projectName == "" {
		beego.Error("No project name available.")
		return Data{}
	}

	// Check for rights
	if ok := models.CheckRight(userName, projectName, "Write"); !ok {
		return Data{
			"Error": "Unsufficient rights for project " + projectName + ".",
		}
	}

	userDir := beego.AppConfig.String("userdata::location") + userName
	projectDir := userDir + "/" + beego.AppConfig.String("userdata::projects") + "/" + projectName

	// Write source files to new project directory
	data := writeSourceFile(s, fileName, projectName, fileType, codeFile, timeStamp, image, alternateFile, alternateType, true)

	outdatedFile := data["OutdatedFile"]
	if outdatedFile != nil && outdatedFile.(string) != "" {
		return data
	}

	// Copy resource files
	for i := 0; i < len(resourceFiles); i++ {
		resProject := resourceFiles[i][:strings.Index(resourceFiles[i], "/")]
		resType := resourceFiles[i][strings.LastIndex(resourceFiles[i], ".")+1:]
		filename := resourceFiles[i][strings.LastIndex(resourceFiles[i], "/")+1:]
		dir := "."

		if resProject == projectName {
			continue
		}

		switch resType {
		case "png":
			dir = beego.AppConfig.String("userdata::imagefiles")
		case "mp3":
			dir = beego.AppConfig.String("userdata::soundfiles")
		}
		err := copyFileContents(userDir+"/"+dir+"/"+resourceFiles[i], projectDir+"/"+dir+"/"+filename)
		if err != nil {
			beego.Error("Cannot copy resource file", resourceFiles[i], "from", userDir, "to", projectDir, "(", err.Error(), ")")
		}
	}

	// Add, commit and push
	if err := models.GitAddCommitPush(userName, projectDir, commit, false); err != nil {
		if err.Error() == "Conflicts" {
			data["Conflicts"] = "Solve conflicts."
		} else {
			beego.Error("Add, commit, push: ", err.Error())
		}
	}

	return data
}
func writeSourceFile(s session.Store, fileName string, project string, fileType string, codeFile string, timeStamp int64, Image string, alternateFile string, alternateType string, overwrite bool) Data {

	// if user is not logged in return
	if s.Get("UserName") == nil {
		return Data{}
	}

	T := models.T
	userName := s.Get("UserName").(string)

	if project == "/" {
		project = ""
	}

	////////////////////////////////////////
	// Retrieve rights and users if it is a project
	rights := []string{}
	users := []string{}
	if project != "" {
		rights = models.GetProjectRightsFromDatabase(userName, project)
		users = models.GetProjectUsersFromDatabase(project)
		beego.Warning("writeSourceFile:", userName, project, rights, users)
	}

	if project != "" && !models.CheckRight(userName, project, "Write") {
		return Data{
			"Error": "Insufficient rights for project " + project,
		}
	}

	var dir string
	if project != "" {
		dir = beego.AppConfig.String("userdata::location") + userName + "/" + beego.AppConfig.String("userdata::projects") + "/" + project + "/" + fileType + "/"
	} else {
		dir = beego.AppConfig.String("userdata::location") + userName + "/" + fileType + "/"
	}

	var (
		file           *os.File
		err            error
		savedTimeStamp int64
	)
	filePath := dir + fileName

	/////////////////////////////////////////
	// Check if directory is there and create if not
	//
	fileStat, err := os.Stat(filePath)
	if os.IsNotExist(err) {
		if err = os.MkdirAll(dir, os.ModePerm); err != nil {
			beego.Error("Cannot create directory", dir)
			return Data{}
		}
	} else if err != nil {
		beego.Error("Error while checking for directory", dir)
		return Data{}
	}

	/////////////////////////////////////////
	// Don't overwrite file unintendedly
	fileStat, err = os.Stat(filePath)
	if !overwrite {
		if !os.IsNotExist(err) {
			return Data{
				"Error": T["websockets_file_exists"],
			}
		} else if err == nil {
			time := fileStat.ModTime().UnixNano() / int64(time.Millisecond)
			// Look if the file changed on disk since last writing
			if time > timeStamp {
				return Data{
					"OutdatedTimeStamp": time,
				}
			}
		}
	}

	/////////////////////////////////////////
	// Also check if alternate file type (png, mp3) would be overwritten
	altSubDir := ""
	switch alternateType {
	case "png":
		altSubDir = beego.AppConfig.String("userdata::imagefiles")
	case "mp3":
		altSubDir = beego.AppConfig.String("userdata::soundfiles")
	}
	altDir := dir[:len(dir)-len(fileType)-1] + altSubDir + "/"
	altFileName := altDir + fileName[:len(fileName)-len(fileType)] + alternateType
	if alternateType != "" {
		fileStat, err = os.Stat(altFileName)
		if !overwrite {
			if !os.IsNotExist(err) {
				return Data{
					"Error": T["websockets_file_exists"],
				}
			}
		}
	}
	beego.Warning("altDir:", altDir, "altFileName:", altFileName)

	/////////////////////////////////////////
	// Create/overwrite file
	if file, err = os.Create(filePath); err != nil {
		beego.Error("Cannot create or overwrite file", filePath)
		return Data{}
	}
	defer file.Close()
	_, err = file.Write([]byte(codeFile))

	////////////////////////////////////////
	// Record timestamps for web app
	if err == nil {
		fileStat, _ = file.Stat()
		savedTimeStamp = fileStat.ModTime().UnixNano() / int64(time.Millisecond)
	} else {
		beego.Error("Cannot write to file", filePath)
		return Data{}
	}

	////////////////////////////////////////
	// Create image file
	createImageFile(Image, filePath)
	if alternateType == "png" {
		createImageFile(alternateFile, altFileName)
	} else if alternateType == "mp3" {
		// create sound file
	}

	return Data{
		"SavedTimeStamp": savedTimeStamp,
		"Rights":         rights,
		"Users":          users,
	}
}