import React from 'react';
import {
  HashRouter as Router,
  Switch,
  Route,
  useParams
} from "react-router-dom";
import Random from './rand';
import './App.css';

let CONFIG;
if (process.env.NODE_ENV === 'production') {
  CONFIG = {
    sleepTimeSeconds: 5 * 60,
    showUI: false,
  }
} else {
  CONFIG = {
    sleepTimeSeconds: 10,
    showUI: true,
  }
}

const IMAGE_CHUNK = 256;
const roundup = (v, mod) => {
  let r = v % mod;
  if (r === 0) {
    return v;
  } else {
    return v + (mod - r);
  }
};

/**
 * Shuffles array in place. ES6 version
 * From https://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array
 * @param {Array} a items An array containing the items.
 */
function shuffle(a) {
  let rng = new Random(new Date().getDay());
    for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(rng.nextFloat() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
}

class Album extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      mediaItems: null,
      idx: 0,
      showUI: props.showUI,
    };
  }
  componentDidMount() {
    let {album} = this.props;
    fetch(process.env.PUBLIC_URL + `/api/album/${album}`)
      .then(res => res.json())
      .then(
        (result) =>  this.setState({mediaItems: result}),
        (error) => this.setState({error}),
      );
  }
  render() {
    // TODO(wathiede): fade transition.
    // TODO(wathiede): pair-up portrait orientation images.
    // TODO(wathiede): fetch an image that maintains the originals aspect ratio
    let w = window.innerWidth * window.devicePixelRatio;
    let h = window.innerHeight * window.devicePixelRatio;
    let ratio = w/h;
    if (ratio > 1) {
      // Landscape image
      w = roundup(w, IMAGE_CHUNK);
      h = (w/ratio).toFixed();
    } else {
      // Portrait image
      h = roundup(h, IMAGE_CHUNK);
      w = (h/ratio).toFixed();
    }
    console.log(`Window size ${window.innerWidth}x${window.innerHeight} with a devicePixelRatio of ${window.devicePixelRatio} for a total size of ${w}x${h}`);

    //let w = roundup(window.innerWidth*window.devicePixelRatio, IMAGE_CHUNK);
    //let h = roundup(window.innerHeight*window.devicePixelRatio, IMAGE_CHUNK);
    let {idx, error, mediaItems, showUI} = this.state;
    if (error !== null) {
      return <h2>Error: {JSON.stringify(error)}</h2>;
    } else if (mediaItems !== null) {
      let landscapes = mediaItems.filter((mi) => {
        let md = mi.mediaMetadata;
        let ratio = md.width/md.height;
        return ratio > 1;
      });

      let portraits = mediaItems.filter((mi) => {
        let md = mi.mediaMetadata;
        let ratio = md.width/md.height;
        return ratio <= 1;
      });

      console.log(`${landscapes.length} landscape photos`);
      console.log(`${portraits.length} portraits photos`);
      let photos;
      if (ratio > 1) {
        console.log('display in landscape mode');
        photos = landscapes;
      } else {
        console.log('display in portrait mode');
        photos = portraits;
      }
      photos = shuffle(photos);

      let numImages = photos.length;
      let nextIdx = (idx+1)%numImages;
      let prevIdx = (numImages+idx-1)%numImages;
      let image = photos[idx];
      let nextImage = photos[nextIdx];
      let prevImage = photos[prevIdx];
      let style = {
        height: '100%',
        width: '100%',
        backgroundColor: 'black',
        backgroundImage: `url(/api/image/${image.id}?w=${w}&h=${h})`,
        backgroundRepeat: 'no-repeat',
        backgroundPosition: 'center center',
        backgroundSize: 'cover',
      };
      let prefetchStyle = {
        position: 'absolute',
        width: '25%',
        height: '25%',
        bottom: 0,
      };
      let leftPrefetchStyle = {
        left: 0,
        ...prefetchStyle
      };
      let rightPrefetchStyle = {
        right: 0,
        ...prefetchStyle
      };
      let ui;
      if (showUI) {
        ui = <div>
          <img
          style={leftPrefetchStyle}
          onClick={(e)=>{
            e.stopPropagation();
            this.setState({idx: prevIdx})
          }}
          src={`/api/image/${prevImage.id}?w=${w}&h=${h}`} alt="prefetch prev" />
          <img
          style={rightPrefetchStyle}
          onClick={(e)=>{
            e.stopPropagation();
            this.setState({idx: nextIdx})
          }}
          src={`/api/image/${nextImage.id}?w=${w}&h=${h}`} alt="prefetch next" />
        </div>;
      }
      return <div style={style} onClick={(e)=>{
        e.stopPropagation();
        this.setState({showUI: !showUI})
      }}>
        { ui }
        </div>;
    } else {
      return <h2>Loading...</h2>;
    }
  }
}

class AlbumIndex extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      error: null,
      albums: null,
    };
  }
  componentDidMount() {
    fetch(process.env.PUBLIC_URL + "/api/albums")
      .then(res => res.json())
      .then(
        (result) =>  this.setState({albums: result}),
        (error) => this.setState({error}),
      );
  }
  render() {
    let {error, albums} = this.state;
    if (error !== null) {
      return <h2>Error: {JSON.stringify(error)}</h2>;
    } else if (albums !== null) {
      return albums.map((a) => {
        let img = <img src="https://via.placeholder.com/256x128" className="mr-3" alt="unset"/>;
        if (a.coverPhotoMediaItemId !== undefined) {
          img = <img src={ `/api/image/${a.coverPhotoMediaItemId}?w=256&h=256` } className="mr-3" alt={ a.title }/>
        }

        let figure = <figure key={ a.id } className="figure">
          {img}
          <figcaption className="figure-caption">{ a.title || "No title" } - { a.mediaItemsCount || 0 } photos </figcaption>
        </figure>;
        return <a key={ a.id } href={ '#' + a.id }>
            { figure }
          </a>
      });
    } else {
      return <h2>Loading...</h2>;
    }
  }
}

const AlbumRoute = ({showUI}) => {
  // We can use the `useParams` hook here to access
  // the dynamic pieces of the URL.
  let { albumId } = useParams();
  return <Album album={albumId} showUI={showUI} />;
}

const App = () => {
  let {showUI} = CONFIG;
  return <Router>
      <Switch>
        <Route exact path="/">
          <div className="container">
            <AlbumIndex />
          </div>
        </Route>
        <Route exact path="/:albumId">
          <AlbumRoute showUI={showUI} />
        </Route>
      </Switch>
    </Router>
}

export default App;
