func GenerateWholeBook(p *Process) error {
	// Get the parts of the config file
	sourcePath := config.SourcePath(source)
	// Set the config file name
	configFile := config.ConfigFile(sourcePath, cfgfile)
	// Log the attempt to read the configuration file
	log.Printf("Reading configuration file %s\n", configFile)
	// Read the configuration
	c, err := config.ReadConfigFromFile(cfgfile, source)
	if err != nil {
		fmt.Printf("Error:: %v\n", err)
		p.Done <- true
		return err
	}

	// Set the source path
	c.SourcePath = sourcePath

	// Process and generate the book
	log.Printf("Generating Book\n")
	err = GenerateBook(p, c)
	if err != nil {
		fmt.Printf("Error:: %v\n", err)
		p.Done <- true
		return err
	}

	return nil
}
func ReadAllModTimes(c *config.Config, p *Process) error {
	// Get the parts of the config file
	sourcePath := config.SourcePath(source)
	configFileLocation := config.ConfigFile(sourcePath, cfgfile)

	// Set the config file name
	configFileInfo, err := os.Stat(configFileLocation)
	if err != nil {
		return err
	}

	// Read all the layouts for html
	htmlLayouts := c.Layouts["html"]

	// Save the config info
	p.ConfigFileInfo = &configFileInfo

	// Get the file info for the pageLayout file
	pageLayoutFile := fmt.Sprintf("%s/%s", p.Source, htmlLayouts.Page)
	pageLayoutFileInfo, err := os.Stat(pageLayoutFile)
	p.PageLayoutFileInfo = &pageLayoutFileInfo

	// Get the file info for the pageLayout file
	indexLayoutFile := fmt.Sprintf("%s/%s", p.Source, htmlLayouts.Index)
	indexLayoutFileInfo, err := os.Stat(indexLayoutFile)
	p.IndexFileInfo = &indexLayoutFileInfo

	// Copy over all the assets
	for _, asset := range c.Assets {
		assetLocation := fmt.Sprintf("%s/%s", p.Source, asset)
		// Get the file info for the pageLayout file
		assetFileInfo, err := os.Stat(assetLocation)
		if err != nil {
			return err
		}
		p.AssetsFileInfo[asset] = &assetFileInfo
	}

	for _, page := range c.TableOfContents {
		// Get the file info for the pageLayout file
		pageFileInfo, err := os.Stat(fmt.Sprintf("%s/%s", p.Source, page.File))
		if err != nil {
			return err
		}

		p.PagesFileInfo[page.File] = &pageFileInfo
	}

	return nil
}
func ReadConfiguration(p *Process) (*config.Config, error) {
	// Get the parts of the config file
	sourcePath := config.SourcePath(source)
	// Set the config file name
	configFile := config.ConfigFile(sourcePath, cfgfile)
	// Log the attempt to read the configuration file
	log.Printf("Reading configuration file %s\n", configFile)
	// Read the configuration
	c, err := config.ReadConfigFromFile(cfgfile, source)
	if err != nil {
		fmt.Printf("Error:: %v\n", err)
		p.Done <- true
		return nil, err
	}

	// Set the source path
	c.SourcePath = sourcePath
	return c, err
}
func GenerateBook(p *Process, c *config.Config) error {
	// Read all the layouts for html
	htmlLayouts := c.Layouts["html"]
	indexLayout := htmlLayouts.Index
	pageLayout := htmlLayouts.Page

	// Get the parts of the config file
	sourcePath := config.SourcePath(source)
	// Set the config file name
	configFile := config.ConfigFile(sourcePath, cfgfile)
	configFileInfo, err := os.Stat(configFile)
	if err == nil {
		p.ConfigFileInfo = &configFileInfo
	}

	// Get the right location for the page layout file
	indexLayoutFile := fmt.Sprintf("%s/%s", p.Source, indexLayout)
	// Get the file info for the pageLayout file
	indexLayoutFileInfo, err := os.Stat(indexLayoutFile)
	if err == nil {
		p.IndexFileInfo = &indexLayoutFileInfo
	}

	// Get the right location for the page layout file
	pageLayoutFile := fmt.Sprintf("%s/%s", p.Source, pageLayout)
	// Get the file info for the pageLayout file
	pageLayoutFileInfo, err := os.Stat(pageLayoutFile)
	if err == nil {
		p.PageLayoutFileInfo = &pageLayoutFileInfo
	}

	// Read the page layout file in
	layoutBytes, err := ioutil.ReadFile(pageLayoutFile)
	if err != nil {
		log.Printf("no layout file found for %s\n", pageLayoutFile)
	}

	// Parse the template into an object
	pageTemplate, err := template.New("pageTemplate").Parse(string(layoutBytes))
	if err != nil {
		log.Printf("invalid template found in %s page template file\n", pageLayoutFile)
	}

	// Copy over all the assets
	for _, asset := range c.Assets {
		assetLocation := fmt.Sprintf("%s/%s", p.Source, asset)
		fileContent, err := ioutil.ReadFile(assetLocation)

		// Get the file info for the pageLayout file
		assetFileInfo, err := os.Stat(assetLocation)
		if err == nil {
			p.AssetsFileInfo[asset] = &assetFileInfo
		}

		if err == nil {
			assetOutputLocation := fmt.Sprintf("%s/%s", c.OutputDirectory, filepath.Base(asset))
			log.Printf("Saving asset to %s\n", assetOutputLocation)

			err = ioutil.WriteFile(assetOutputLocation, fileContent, 0755)
			if err != nil {
				log.Fatalf("Failed to save the asset %s to %s\n", asset, assetOutputLocation)
			}
		} else {
			log.Fatalf("Could not locate the asset %s\n", asset)
		}
	}

	// Read all the pages in
	for pageIndex, page := range c.TableOfContents {
		log.Printf("Generate page %s\n", page.File)

		// Split the file up so we can get the "name"
		fileNameParts := strings.Split(page.File, ".")
		fileName := strings.Join(fileNameParts[0:(len(fileNameParts)-1)], ".")

		// Read the page
		pageFile := fmt.Sprintf("%s/%s", p.Source, page.File)

		// Get the file info for the pageLayout file
		pageFileInfo, err := os.Stat(pageFile)
		if err != nil {
			return err
		}

		if err == nil {
			p.PagesFileInfo[page.File] = &pageFileInfo
		}

		// Read the page into memory
		data, err := ioutil.ReadFile(pageFile)
		if err != nil {
			return err
		}

		// Render the mardown
		html := p.CustomTransformer.Transform(data)

		// Pass to the template if it's defined
		if pageTemplate != nil {
			// Output buffer
			buffer := bytes.NewBuffer(nil)
			// Render the template
			err = pageTemplate.Execute(buffer, BuildContext(pageIndex, string(html), c))
			if err != nil {
				log.Fatalf("Failed to execute template %s\n", pageLayoutFile)
				os.Exit(0)
			}

			// Save the data as the new page
			html = buffer.Bytes()
		}

		// Let's write the resulting page out
		err = ioutil.WriteFile(fmt.Sprintf("%s/%s.html", c.OutputDirectory, fileName), html, 0755)
		if err != nil {
			return err
		}
	}

	return nil
}
func WatchMode(delay int64, p *Process) {
	go func() {
		for true {
			// Get the parts of the config file
			sourcePath := config.SourcePath(source)
			configFileLocation := config.ConfigFile(sourcePath, cfgfile)

			// Set the config file name
			configFileInfo, err := os.Stat(configFileLocation)
			if err != nil {
				log.Printf("Failed to read configuration file from %s\n", configFileLocation)
				continue
			}

			// Read the configuration
			c, err := config.ReadConfigFromFile(cfgfile, source)
			if err != nil {
				log.Printf("Failed to read configuration file from %s\n", configFileLocation)
				continue
			}

			// Point to the actual instance
			configFileInfoInstance := *p.ConfigFileInfo

			// If config time finished
			if !configFileInfo.ModTime().Equal(configFileInfoInstance.ModTime()) {
				log.Printf("Configuration file changed, regenerating whole book\n")
				// Re-generate the whole book
				GenerateWholeBook(p)
				// Save the new configuration file info
				p.ConfigFileInfo = &configFileInfo
				// Done, let's watch again
				continue
			}

			// Read all the layouts for html
			htmlLayouts := c.Layouts["html"]
			indexLayout := htmlLayouts.Index
			pageLayout := htmlLayouts.Page

			// Get the file info for the pageLayout file
			pageLayoutFile := fmt.Sprintf("%s/%s", p.Source, pageLayout)
			pageLayoutFileInfo, err := os.Stat(pageLayoutFile)
			if err != nil {
				log.Printf("Index layout file changed, regenerating whole book\n")
				// Re-generate the whole book
				GenerateWholeBook(p)
				// Update the time
				p.PageLayoutFileInfo = &pageLayoutFileInfo
				continue
			}

			// Get the file info for the pageLayout file
			indexLayoutFile := fmt.Sprintf("%s/%s", p.Source, indexLayout)
			indexLayoutFileInfo, err := os.Stat(indexLayoutFile)
			if err != nil {
				log.Printf("Index layout file changed, regenerating whole book\n")
				// Re-generate the whole book
				GenerateWholeBook(p)
				// Update the time
				p.IndexFileInfo = &indexLayoutFileInfo
				continue
			}

			// Read the page layout file in
			layoutBytes, err := ioutil.ReadFile(pageLayoutFile)
			if err != nil {
				log.Printf("no layout file found for %s\n", pageLayoutFile)
			}

			// Parse the template into an object
			pageTemplate, err := template.New("pageTemplate").Parse(string(layoutBytes))
			if err != nil {
				log.Printf("invalid template found in %s page template file\n", pageLayoutFile)
			}

			// Copy over all the assets
			for _, asset := range c.Assets {
				assetLocation := fmt.Sprintf("%s/%s", p.Source, asset)
				fileContent, err := ioutil.ReadFile(assetLocation)

				// Get the file info for the pageLayout file
				assetFileInfo, err := os.Stat(assetLocation)
				if err == nil {
					modTime := *p.AssetsFileInfo[asset]

					if modTime != nil && modTime.ModTime().Equal(assetFileInfo.ModTime()) {
						continue
					}

					p.AssetsFileInfo[asset] = &assetFileInfo
				}

				if err == nil {
					assetOutputLocation := fmt.Sprintf("%s/%s", c.OutputDirectory, filepath.Base(asset))
					log.Printf("Saving asset to %s\n", assetOutputLocation)

					err = ioutil.WriteFile(assetOutputLocation, fileContent, 0755)
					if err != nil {
						log.Fatalf("Failed to save the asset %s to %s\n", asset, assetOutputLocation)
					}
				} else {
					log.Fatalf("Could not locate the asset %s\n", asset)
				}
			}

			// We only re-generate pages that have changed
			// Read all the pages in
			for pageIndex, page := range c.TableOfContents {
				// Split the file up so we can get the "name"
				fileNameParts := strings.Split(page.File, ".")
				fileName := strings.Join(fileNameParts[0:(len(fileNameParts)-1)], ".")

				// Read the page
				pageFile := fmt.Sprintf("%s/%s", p.Source, page.File)

				// Get the file info for the pageLayout file
				pageFileInfo, err := os.Stat(pageFile)
				if err == nil {
					modTime := *p.PagesFileInfo[page.File]

					if modTime != nil && modTime.ModTime().Equal(pageFileInfo.ModTime()) {
						continue
					}

					log.Printf("Generate page %s\n", page.File)
					p.PagesFileInfo[page.File] = &pageFileInfo
				}

				// Read the page into memory
				data, err := ioutil.ReadFile(pageFile)
				if err != nil {
					continue
				}

				// Render the mardown
				html := p.CustomTransformer.Transform(data)

				// Pass to the template if it's defined
				if pageTemplate != nil {
					// var buffer bytes.Buffer
					buffer := bytes.NewBuffer(nil)
					err = pageTemplate.Execute(buffer, BuildContext(pageIndex, string(html), c))
					if err != nil {
						log.Fatalf("Failed to execute template %s\n", pageLayoutFile)
						os.Exit(0)
					}

					// Save the data as the new page
					html = buffer.Bytes()
				}

				// Let's write the resulting page out
				err = ioutil.WriteFile(fmt.Sprintf("%s/%s.html", c.OutputDirectory, fileName), html, 0755)
				if err != nil {
					continue
				}
			}

			// Just sleep a bit and watch again
			time.Sleep(time.Duration(delay) * time.Millisecond)
		}
	}()

	// Wait until we are done
	<-p.Done
}